2013-06-26 34 views
-1

我有這個疑問:爲什麼重複查詢結果,沒有「GROUP BY」?

SELECT C.ID_PASS, C.ID_MERCE, CTRL.ESITO, M.ID_CAT, M.QTA, M.DESCRIZ, 
    CTRL.ID_PUNTO, CTRL.ID_ADDETTO, C.DATE_OPEN, C.DATE_CLOSE, C.NOTE 

FROM CONTESTAZIONI C, CONTROLLI CTRL, FUNZIONARI F, ADDETTI A, MERCI M 

WHERE A.ID=CTRL.ID_ADDETTO 
    AND A.ID_FUNZ=501 
    AND M.ID=C.ID_MERCE 
    AND M.ID_PASS=C.ID_PASS 
    AND CTRL.ESITO > 1 
GROUP BY C.ID_PASS; 

爲什麼,如果我不加GROUP BY C.ID_PASS,我能得到20行(而不是2)。

+1

您正在加入5個表格,但兩個表格之間只有明確的關係。 (M <-> C和A <-> CTRL)。 –

回答

1

在與「,」運算符進行連接時,您會得到一個交叉產品。您應該將所有表中的ID包含在where子句中!

基本上,您需要通過確保其行ID的均等性將所有5個錶鏈接在一起,因爲如註釋中所述,您有兩組表,但它們沒有鏈接,因此得到的集有很多重複。

1

當使用聚合函數(如SUM或COUNT)時,GROUP BY用於將行組合在一起。

如果你有,例如,4條記錄,其中說各爲2卡斯特ID,每一個值: -

CustId Spend 
1   10 
1   20 
2   30 
2   40 

如果你想知道每個客戶你會總每個值的使用類似: -

SELECT CustId, SUM(Spend) FROM SomeTable GROUP BY CustId 

這將使你

CustId Sum(Spend) 
1   30 
2   70 

部分的它是什麼祛瘀e複製行並將所有值彙總成一行。

它可以被濫用,沒有聚合函數來刪除重複項,這就是你所做的。因此,2條記錄不是20條。

請注意,如果SELECT中的字段不在GROUP BY變量中,並且這些字段不是100%依賴字段組,則該字段的值是不確定的。

例如

CustId Spend ShopId 
1   10  1 
1   20  2 
2   30  3 
2   40  4 

如果你想知道總的每個你會使用類似客戶的每個值: -

SELECT CUSTID,ShopId,SUM(花)FROM SomeTable GROUP BY CUSTID

這將使你

CustId Sum(Spend) ShopId 
1   30   Could be 1 or could be 2 
2   70   Could be 3 or could be 4 

在查詢這可能適用於CTRL.ESITO,M.ID_CAT,M.QTA,M.DESCRIZ, CTRL.ID_PUNTO,CTRL.ID_ADDETTO。

1

您正在對錶進行隱式交叉連接。嘗試使用不同類型的連接,例如Inner,Right或Left。

例如:

現代(意思是,1992年後)的
SELECT * 
FROM CONTESTAZIONI c 
INNER JOIN CONTROLLI ctrl ON c.ID = ctrl.ContId 
1

一個優勢明確的JOIN符號是,你是不太可能忘記了加盟的條件。你有5張桌子;你需要(至少)4個連接條件。你的SQL只有2個連接條件(其中一個是複合連接)。你沒有給我們足夠的架構,以確保未來與加盟右列的,但你的查詢可能應該是這樣的:

SELECT C.ID_PASS, C.ID_MERCE, CTRL.ESITO, M.ID_CAT, M.QTA, M.DESCRIZ, 
     L.ID_PUNTO, L.ID_ADDETTO, C.DATE_OPEN, C.DATE_CLOSE, C.NOTE 
    FROM ADDETTI  A 
    JOIN CONTROLLI  L ON A.ID = L.ID_Addetto 
    JOIN CONTESTAZIONI C ON A.xxx1 = C.xxx2 
    JOIN FUNZIONARI F ON C.yyy1 = F.yyy2 
    JOIN MERCI   M ON M.ID = C.ID_Merce AND M.ID_Pass = C.ID_Pass 
WHERE A.ID_FUNZ=501 
    AND L.ESITO > 1; 

請注意,您顯示連接A和L(從改名CTRL)以及M和C. C到A和F到C的連接是半任意猜測(列名稱xxx1等是您的真實列名的佔位符)。您需要了解您的模式並進行適當的連接。

+0

漂亮的語法。 – user2452426

0

感謝任何人。現在我明白了:我必須把我所選擇的所有表格都放在一起(當然只有那些關係);沒有這個連接,我得到一個交叉產品。我可以加入「JOIN ... ON ...」或「WHERE ...」。我加入了WHERE。現在可以正常工作:

SELECT C.ID_PASS, C.ID_PUNTO, C.ID_ADDETTO, C.TIME_START, 
    C.TIME_END, C.ESITO, P.ID_NAZ, C.ID_MERCE, M.QTA, M.DESCRIZ, M.ID_CAT 
FROM CONTROLLI C, PASSEGGERI P, MERCI M, FUNZIONARI F, CATEGORIE, ADDETTI, NAZIONI 
WHERE 
    ADDETTI.ID=C.ID_ADDETTO 
AND P.ID=M.ID_PASS 
AND P.ID_NAZ=NAZIONI.ID 
AND M.ID_PASS=C.ID_PASS AND M.ID=C.ID_MERCE -- composite PK (so another AND reuqired) 
AND M.ID_CAT=CATEGORIE.ID 
AND F.ID=ADDETTI.ID_FUNZ 
AND ESITO > 1 
AND F.ID = 501