我基本上有一个表可以保存每个日期的计数。我想创建一个查询,它给出了整个表的总计数,以及昨天的总计数。但是当我尝试两次加入表时,聚合关闭了。以下是复制结果的方法。
CREATE TABLE a (id int primary key);
CREATE TABLE b (a_id int, b_id int, date date, count int, primary key (a_id,b_id,date));
INSERT INTO a VALUES (1);
INSERT INTO b VALUES (1, 1, UTC_DATE(), 5);
INSERT INTO b VALUES (1, 2, UTC_DATE(), 10);
INSERT INTO b VALUES (1, 1, UTC_DATE()-1, 7);
INSERT INTO b VALUES (1, 2, UTC_DATE()-1, 12);
SELECT A.id,SUM(B.count) AS total_count,SUM(Y.count) AS y FROM a AS A
LEFT JOIN b AS B ON (B.a_id=A.id)
LEFT JOIN b AS Y ON (Y.a_id=A.id AND Y.date=UTC_DATE()-1)
GROUP BY A.id;
Results in:
+----+-------------+------+
| id | total_count | y |
+----+-------------+------+
| 1 | 68 | 76 |
+----+-------------+------+
The correct result should be:
+----+-------------+------+
| id | total_count | y |
+----+-------------+------+
| 1 | 34 | 22 |
+----+-------------+------+
这里发生了什么?这是mysql中的错误还是我不了解连接是如何工作的。
答案 0 :(得分:8)
不,这不是MySQL中的错误。
您的JOIN条件正在生成“重复”行。 (删除聚合函数和GROUP BY,你会看到发生了什么。
表“a”中的那一行匹配表“b”中的四行。这一切都很好,很好。但是当您将连接添加到第三个表(“y”)时,从第三个“y”表(两行)返回的每一行都与“b”表中的每一行“匹配”...所以你风结果集中总共有八行。 (这就是“total_count”加倍的原因。)
要获取您指定的结果集,您不需要第二次加入该表“b”。相反,只需使用条件测试来确定“计数”是否应该包含在“y”总数中。
e.g。
SELECT a.id
, SUM(b.count) AS total_count
, SUM(IF(b.date=UTC_DATE()-1 ,b.count,0)) AS y
FROM a a
LEFT
JOIN b b ON (b.a_id=a.id)
GROUP BY a.id;
请注意,MySQL IF
表达式可以替换为等效的ANSI CASE
表达式,以提高可移植性:
, SUM(CASE WHEN b.date=UTC_DATE()-1 THEN b.count ELSE 0 END) AS y
如果你确实想第二次联接到那个“b”表,你会希望JOIN条件是这样的,“y”中的一行最多匹配“b”中的一行,所以以免引入任何重复。所以你基本上需要连接条件来包含主键中的所有列。
(请注意,表“y”的连接条件中的谓词保证来自“y”的每个匹配不会超过“b”中的一行):
SELECT a.id
, SUM(b.count) AS total_count
, SUM(y.count) AS y
FROM a a
LEFT
JOIN b b
ON b.a_id=a.id
LEFT
JOIN b y
ON y.a_id = b.a_id
AND y.b_id = b.b_id
AND y.date = b.date
AND y.date = UTC_DATE()-1
GROUP BY a.id;
(要使第一个语句返回相同的结果集,使用潜在的NULL代替零,您需要将IF表达式中的'0'常量替换为'NULL'。
, SUM(IF(b.date=UTC_DATE()-1 ,b.count,NULL)) AS y
答案 1 :(得分:5)
SELECT A.id,b_count AS total_count,y_count as y
FROM a AS A
LEFT JOIN (select a_id,SUM(B.Count) b_count from b
group by B.A_id) AS B1 ON (B1.a_id=A.id)
LEFT JOIN (select a_id,SUM(Count) y_count from b
where date=UTC_DATE()-1
group by B.A_id) AS Y ON (Y.a_id=A.id)