我通常在这里找到问题的答案。如果没有,我知道这可能是因为我看起来不够深。但是这一次,我所看到的答案都不符合我的需求。所以这就是:
我想使用MySQL服务器从两个表构建报告:
ID Email ID Date Spent
----------------------- ---------------------------
A123 a@test.com A123 3.3.14 2.50
B102 b@test.com A123 7.3.14 3.50
yum yum@a.com B102 4.4.14 7.00
(null) (null)
我想针对给定的时间戳进行报告,例如。从3.1.2014到3.31.14,我得到了系统的所有ID的列表,以及他们发送的相应金额,即使他们没有花费任何东西。
因此,从上表中,我们想要检索2014年3月的月份(从3.1.2014到3.31.14),我想得到:
ID Spent
------------------
A123 6.00
B102 7.00
yum NULL
我不介意为那些没有花钱的用户提供NULL或0。到目前为止,我已经得到了这个:
SELECT ID,
sum(Spent) AS Spent
FROM expenses
WHERE expenses.date >= '2014-03-01 00:00:00'
AND expenses.date < '2014-03-31 00:00:00'
GROUP BY expenses.ID
UNION
SELECT users.ID,
NULL AS Spent
FROM users
WHERE users.ID NOT IN
(SELECT expenses.ID
FROM expenses
WHERE expenses.date >= '2014-03-01 00:00:00'
AND expenses.date < '2014-03-31 00:00:00'
GROUP BY expenses.ID)
ORDER BY ID;
您可以在here中查看以上代码。
它按预期工作,但在我的数据库的实际情况中,结果查询中的行数大于users
中唯一行的数量。
我已经检查过expenses
表中的所有ID都在users
表中,情况就是这样。我测试过:
SELECT ID FROM expenses
WHERE expenses.date >= '2014-03-01 00:00:00'
AND expenses.date < '2014-03-31 00:00:00'
AND ID NOT IN (SELECT users.ID FROM users);
并返回一个空集,这与预期的一样。
我必须遗漏一些东西,但我不知道是什么。有人可以提供一些见解吗?我对MySQL很陌生,也许还有更好的方法。
答案 0 :(得分:2)
我认为您需要left outer join
而不是union
:
SELECT u.ID, sum(e.Spent) AS Spent
FROM users u left outer join
expenses e
on u.id = e.id and
e.date >= '2014-03-01 00:00:00' and
e.date < '2014-03-31 00:00:00'
GROUP BY u.ID;
请注意,在SQL Fiddle中的数据中,这将返回四行,因为NULL
中的users
值行。
答案 1 :(得分:0)
您可以连接两个表(用户和费用)以获得相同的结果(http://sqlfiddle.com/#!2/738ea6/5)。这将更加快速且易于理解。
SELECT expenses.ID,
sum(Spent) AS Spent
FROM expenses, users
WHERE expenses.date >= '2014-03-01 00:00:00'
AND expenses.date < '2014-03-31 00:00:00'
AND users.ID = expenses.ID
GROUP BY expenses.ID
ORDER BY ID;
答案 2 :(得分:0)
在第二个查询中分组?
SELECT ID,
sum(Spent) AS Spent
FROM expenses
WHERE expenses.date >= '2014-03-01 00:00:00'
AND expenses.date < '2014-03-31 00:00:00'
GROUP BY expenses.ID
UNION
SELECT users.ID,
NULL AS Spent
FROM users
WHERE users.ID NOT IN
(SELECT expenses.ID
FROM expenses
WHERE expenses.date >= '2014-03-01 00:00:00'
AND expenses.date < '2014-03-31 00:00:00'
GROUP BY expenses.ID)
GROUP BY ID
ORDER BY ID;