为什么重复查询结果,没有“GROUP BY”?

时间:2013-06-26 14:08:50

标签: mysql sql

我有这个问题:

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行)。

5 个答案:

答案 0 :(得分:1)

使用“,”运算符进行连接时会得到一个交叉产品。您应该将所有表中的ID包含在where子句中!

基本上,您需要通过确保其行的ID的相等性来将所有5个表链接在一起,因为如注释中所述,您有两组表,但它们没有链接,因此结果集具有大量重复项。

答案 1 :(得分:1)

GROUP BY用于在使用聚合函数(例如SUM或COUNT。)时将行组合在一起。

例如,如果您有4条记录,每条帐户名称为2条,则每条记录都有一个值: -

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

它的部分功能是删除重复的行并将所有值汇总到一行。

如果没有聚合函数可以滥用它来删除重复项,这就是你所做的。因此有2条记录而不是20条。

请注意,如果SELECT中的字段不在GROUP BY变量中,并且不是100%依赖于group by字段,那么该字段的值是不确定的。

例如

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。

答案 2 :(得分:1)

您正在对表进行隐式交叉连接。尝试使用不同类型的Join,例如Inner,Right或Left。

示例:

SELECT *
FROM CONTESTAZIONI c 
INNER JOIN CONTROLLI ctrl ON c.ID = ctrl.ContId

答案 3 :(得分:1)

现代(意思是1992年后)明确的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等等是你真实列名的占位符);您将需要了解您的架构并进行适当的连接。

答案 4 :(得分:0)

感谢大家。现在我明白了:我必须将我选择的所有表格加在一起(当然只有关系中的表格);没有这个加入我得到一个交叉产品。我可以加入" JOIN ...... ON ..."或者"在哪里......"。我和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