SQL Story摘錄(一)————簡單查詢初探 (轉)

worldblog發表於2007-12-13
SQL Story摘錄(一)————簡單查詢初探 (轉)[@more@]

在CSDN上回貼時,我總是苦口婆心地勸告樓上樓下的朋友們多用聯接。可響應甚微。往往一個簡單的功能,也一定要寫成子查詢或遊標,弄得非常複雜冗長。的確,這樣寫對於初學者來說,費力不費腦,思路比較好理解。所以往往得分的也是這些回貼。可事實上,如果你真正熟悉了的風格,你會明白,聯接查詢才是最直接、最清晰、最有力的方法,而更好的辦法就是無招勝有招,一條簡單查詢結束戰鬥。下面我舉幾個例子來證明一下這個觀點。
例1-1、重複記錄的查詢和處理
總有一些朋友在網上問,一個表中,有重複的記錄,怎麼辦?當然,一個設計風格良好的關係型,每個表都應該有主鍵、有唯一,所以壓根就不該有重複記錄。不過有時還是會出現不該出現的事,比如“七.七事變”,比如“9.11”……咳咳,其實我想說的是,有時會有人根本沒有資料庫的概念,他就不知道主鍵是什麼,或者隨意建了一個自動標識的ID列充數(其實這也沒什麼,沒有人天生會設計資料庫,關鍵是願不願承認自己的不足並且改進)。更常見的是我們的資料可能來自一些電子表格或文字,匯入到資料庫中時才發現問題。
這裡,我們建立一個表,表示某商店的存貨。我有意沒有加入任何索引和,這樣,它會很容易地出問題(就像實驗室裡的裸鼠)。
CREATE TABLE PRODUCT(
ID INT, PNAME CHAR(20),
PRICE MONEY, NUMBER INT,
PDESCRIPTION VARCHAR(50))
現在,我們可以向其中插入一些資料:
IDPNAMEPRICENUMBERPDESCRIPTION
1Apple 123000

1Apple 123000

2Banana 16.997600

3Olive 25.224500

4Orange 15.995500

4Coco Nut 40.992000

5Pineapple 302500

6Olive 25.223000


這裡有一些明顯的問題,前兩行完全一樣,這樣的重複資料一點意義都沒有,只會添亂。InterBase還好點,在它的IBConsole中可以直接修改它們。可在中,根本無法區分這兩行,當我們試圖對其中任一行修改時會收到一個錯誤資訊。事實上,這也是一個關係型資料庫應有的反應。那我們應該怎麼辦呢?
事實上,處理它的方法比找出錯誤資料還簡單,聯接查詢都用不到。用一條SQL語句
DISTINCT * FROM PRODUCT
就可以把重複資料掉,生成一個包括正常資料的資料集。結果如下:
IDPNAMEPRICENUMBERPDESCRIPTION
1Apple 123000

2Banana 16.997600

3Olive 25.224500

4Orange 15.995500

4Coco Nut 40.992000

5Pineapple 302500

6Olive 25.223000


對於支援SELECT …… INTO……FROM語句的資料庫來說,這樣一句
SELECT DISTINCT * INTO NewTable FROM PRODUCT
就可把資料匯入到一個新表(NewTable )中。或者可以用INERT INTO …… SELECT DISTINCT * FROM ……把它匯入到一個現有的表中。總之有了正確的資料集,再如何處理就好辦了。相信大家知道這個合併重複資料的關鍵字DISTINCT後,再不會用遊標來處理重複資料了吧。
這是第一步,有時可能我們不想一下把它們壓縮掉,而是想先看看到底誰出了問題。好的,用下面的語句可以找出重複的記錄,最右邊一列“ROW_COUNT”表示這行資料在表中重複的次數:
SELECT ID, PNAME, PRICE, NUMBER, PDESCRIPTION, COUNT(*) ROW_COUNT
FROM PRODUCT
GROUP BY ID, PNAME, PRICE, NUMBER, PDESCRIPTION
HAVING COUNT(*) > 1
IDPNAMEPRICENUMBERPDESCRIPTIONROW_COUNT
1Apple123000NULL2

 


(所影響的行數為 1 行)
其實就是關鍵字GROUP BY …… HAVING和統計COUNT的一個簡單運用,記得在GROUP BY 後面寫上完整的欄位列表。這表示我們要的是那些完全一致的資料,每個欄位都一樣。
PRODUCT表中的資料很多時,用前面的方法直接生成正確的資料集很低。現在有了這個結果集,我們可以高效率工作了。現在,我們用
SELECT ID, PNAME, PRICE, NUMBER, PDESCRIPTION
FROM PRODUCT
GROUP BY ID, PNAME, PRICE, NUMBER, PDESCRIPTION
HAVING COUNT(*) > 1
把重複的資料生成為一個經過壓縮的正確資料集,用前述的方法匯出到一個臨時表中,然後用
DELETE FROM PRODUCT
WHERE ID IN (
SELECT ID
FROM PRODUCT
GROUP BY ID, PNAME, PRICE, NUMBER, PDESCRIPTION
HAVING COUNT(*) > 1
)
把重複資料從PRODUCT表中刪除,再把壓縮好的資料插入PRODUCT。現在PRODUCT表中不再有完全重複,不可標識的資料了。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992641/,如需轉載,請註明出處,否則將追究法律責任。

相關文章