cal*_*die 1 mysql join sum between
我有两个表需要加入...我想在'id'上加入table1和table2 - 但是在表2中,id不是唯一的.我只希望为表2返回一个值,并且此值表示在指定日期范围(比如一个月)内名为"total_sold"的列的总和,但是我同时想要多个日期范围...
SELECT ta.id, sum(tb.total_sold) as total_sold_this_week, sum(tc.total_sold) as total_sold_this_month
FROM table_a as ta
LEFT JOIN table_b as tb ON ta.id=tb.id AND tb.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -1 WEEK) AND NOW()
LEFT JOIN table_b as tc ON ta.id=tc.id AND tc.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -1 MONTH) AND NOW()
GROUP BY ta.id
Run Code Online (Sandbox Code Playgroud)
这可行,但不会对行进行求和 - 只为每个id返回一行...如何从表b中获取总和而不是只有一行?请批评问题的格式是否可以使用更多的工作 - 如果需要,我可以重写并提供样本数据 - 这是一个更大问题的平凡版本.
-谢谢
解决此问题的一种方法是使用子查询. LEFT JOIN为右表中的每个匹配创建一个新的"结果",因此使用两个LEFT JOIN创建的ROWS比你想要的多.你可以只选择你想要的值,但这可能很慢:
SELECT ta.id,
(SELECT SUM(total_sold) as total_sold
FROM table_b
WHERE date_sold BETWEEN ADDDATE(NOW(), INTERVAL -1 WEEK) AND NOW()
AND id=ta.id) as total_sold_this_week,
(SELECT SUM(total_sold) as total_sold
FROM table_b
WHERE date_sold BETWEEN ADDDATE(NOW(), INTERVAL -1 MONTH) AND NOW()
AND id = ta.id) as total_sold_this_month
FROM table_a ta;
Run Code Online (Sandbox Code Playgroud)
结果:
+----+----------------------+-----------------------+ | id | total_sold_this_week | total_sold_this_month | +----+----------------------+-----------------------+ | 1 | 3 | 7 | | 2 | 4 | 4 | | 3 | NULL | NULL | +----+----------------------+-----------------------+ 3 rows in set (0.04 sec)
此方法不使用子查询(并且在较大的数据集上可能会更快).我们希望使用"最大"日期范围将table_a和table_b连接在一起,然后使用SUM()基于a CASE的计算"较小范围".
SELECT ta.*,
SUM(total_sold) as total_sold_last_month,
SUM(CASE
WHEN date_sold BETWEEN NOW() - INTERVAL 1 WEEK AND NOW()
THEN total_sold
ELSE 0
END) as total_sold_last_week
FROM table_a AS ta
LEFT JOIN table_b AS tb
ON ta.id=tb.id AND tb.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -1 MONTH) AND NOW()
GROUP BY ta.id;
Run Code Online (Sandbox Code Playgroud)
这将返回与子查询示例几乎相同的结果集:
+----+-----------------------+----------------------+ | id | total_sold_last_month | total_sold_last_week | +----+-----------------------+----------------------+ | 1 | 7 | 3 | | 2 | 4 | 4 | | 3 | NULL | 0 | +----+-----------------------+----------------------+ 3 rows in set (0.00 sec)
唯一的区别是0代替NULL.您可以使用此方法汇总尽可能多的日期范围,但仍可能最好限制返回到ON子句中最大范围的行.
只是为了说明它是如何工作的:删除GROUP BY和SUM()调用,并添加date_sold到SELECT返回:
+----+------------+-----------------------+----------------------+ | id | date_sold | total_sold_last_month | total_sold_last_week | +----+------------+-----------------------+----------------------+ | 1 | 2010-04-30 | 2 | 2 | | 1 | 2010-04-24 | 2 | 0 | | 1 | 2010-04-24 | 2 | 0 | | 1 | 2010-05-03 | 1 | 1 | | 2 | 2010-05-03 | 4 | 4 | | 3 | NULL | NULL | 0 | +----+------------+-----------------------+----------------------+ 6 rows in set (0.00 sec)
现在,当你GROUP BY id和SUM()两个total_sold列有你的结果!
在将两个不同的日期范围放入混合之前,您可以使用GROUP BYtable1上的表id进行分组,并使用SUM()聚合函数来添加返回的行.
SELECT ta.id, SUM(tb.total_sold) as total_sold_this_week
FROM table_a as ta
LEFT JOIN table_b as tb
ON ta.id=tb.id AND tb.date_sold BETWEEN ADDDATE(NOW(),INTERVAL -3 WEEK) AND NOW()
GROUP BY ta.id
Run Code Online (Sandbox Code Playgroud)
+----+----------------------+ | id | total_sold_this_week | +----+----------------------+ | 1 | 7 | | 2 | 4 | | 3 | NULL | +----+----------------------+ 3 rows in set (0.00 sec)
NOW() 是2010-05-03
mysql> select * from table_a; select * from table_b; +----+ | id | +----+ | 1 | | 2 | | 3 | +----+ 3 rows in set (0.00 sec) +----+------------+------------+ | id | date_sold | total_sold | +----+------------+------------+ | 1 | 2010-04-24 | 2 | | 1 | 2010-04-24 | 2 | | 1 | 2010-04-30 | 2 | | 1 | 2010-05-03 | 1 | | 2 | 2010-05-03 | 4 | +----+------------+------------+ 5 rows in set (0.00 sec)
| 归档时间: |
|
| 查看次数: |
3177 次 |
| 最近记录: |