Mysql 为什么重复查询结果,而没有;按“分组”;?
我有一个疑问:Mysql 为什么重复查询结果,而没有;按“分组”;?,mysql,sql,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
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;
为什么,如果我不按C.ID\u PASS添加
分组,我会得到20行(而不是2行)。使用运算符进行连接时,会得到一个叉积。您应该在where子句中包含所有表的ID
基本上,您需要通过确保所有5个表的行ID相等来将它们链接在一起,因为如注释中所述,您有两组表,但它们没有链接,因此结果集有许多重复项 GROUP BY用于在使用聚合函数(如SUM或COUNT)时将行分组在一起
例如,如果您有4条记录,每个客户id有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
CustId Sum(Spend) ShopId
1 30 Could be 1 or could be 2
2 70 Could be 3 or could be 4
它所做的部分工作是删除重复的行,并将所有值汇总到一行中
如果没有聚合函数来删除重复项,它可能会被误用,这就是您所做的。因此,只有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, SUM(Spend) FROM SomeTable GROUP BY CustId
按CustId从SomeTable组中选择CustId、ShopId、SUM(支出)
这会给你
CustId Sum(Spend)
1 30
2 70
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\u PUNTO,CTRL.ID\u ADDETTO。您正在表上执行隐式交叉联接。尝试使用不同类型的联接,例如内部联接、右侧联接或左侧联接
例如:
SELECT *
FROM CONTESTAZIONI c
INNER JOIN CONTROLLI ctrl ON c.ID = ctrl.ContId
现代(意思是1992年后)显式连接表示法的一个优点是,您不太可能忘记连接条件。你有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
等是真实列名的占位符);您需要了解您的模式并进行适当的联接。感谢everbody。现在我明白了:我必须将我放在select中的所有表连接在一起(当然,只有关系中的表);没有这个连接,我得到一个叉积。我可以加入“加入…在…”或“在哪里…”。我和何处会合。现在可以正常工作了:
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
您将连接5个表,但在两组表之间只有显式关系。(MC和ACTRL)。