-1

我有这个查询:

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

4

5 回答 5

1

您正在对表进行隐式交叉连接。尝试使用不同类型的连接,例如内连接、右连接或左连接。

例子:

SELECT *
FROM CONTESTAZIONI c 
INNER JOIN CONTROLLI ctrl ON c.ID = ctrl.ContId
于 2013-06-26T17:47:36.790 回答
1

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

它所做的部分工作是删除重复的行并将所有值汇总为一行。

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

请注意,如果 SELECT 中的字段不在 GROUP BY 变量中,并且不是 100% 依赖于分组依据字段,则该字段的值是不确定的。

例如

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

如果您想知道每个客户的每个价值的总和,您可以使用以下内容:-

从 SomeTable GROUP BY CustId 中选择 CustId、ShopId、SUM(Spend)

这会给你

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 字段。

于 2013-06-26T15:38:56.503 回答
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等是真实列名的占位符); 您将需要了解您的架构并进行适当的连接。

于 2013-06-26T23:22:51.370 回答
1

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

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

于 2013-06-26T14:12:44.490 回答
0

感谢大家。现在我明白了:我必须将我放入 select 的所有表连接在一起(当然只有那些有关系的表);没有这个加入,我得到一个交叉产品。我可以加入“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
于 2013-06-27T15:05:14.920 回答