我有两个表格描述用户及其付款:
CREATE TABLE test_users
(id int IDENTITY NOT NULL,
name varchar(25),
PRIMARY KEY (id));
CREATE TABLE test_payments
(id int IDENTITY NOT NULL,
user_id int NOT NULL,
money money NOT NULL,
date datetime NOT NULL,
PRIMARY KEY (id));
INSERT INTO test_users (name)
VALUES ('john');
INSERT INTO test_users (name)
VALUES ('peter');
INSERT INTO test_payments (user_id, money, date)
VALUES (1, $1, CONVERT(datetime, '15.12.2012'));
INSERT INTO test_payments (user_id, money, date)
VALUES (1, $2, CONVERT(datetime, '16.12.2012'));
INSERT INTO test_payments (user_id, money, date)
VALUES (2, $1, CONVERT(datetime, '16.12.2012'));
INSERT INTO test_payments (user_id, money, date)
VALUES (2, $3, CONVERT(datetime, '17.12.2012'));
INSERT INTO test_payments (user_id, money, date)
VALUES (1, $1, CONVERT(datetime, '19.12.2012'));
表test_users:
id name
-------------
1 john
2 peter
表test_payments:
id user_id money last_activity
---------------------------------------
1 1 1.0000 2012-12-15
2 1 2.0000 2012-12-16
3 2 1.0000 2012-12-16
4 2 3.0000 2012-12-17
5 1 1.0000 2012-12-19
我需要制作一个用户统计信息,告诉我:
例如,参加15-18.12.12期间我期望得到以下结果:
name total last_activity
--------------------------------
peter $4 2012-12-17
john $3 2012-12-19
我尝试过以下查询:
SELECT u.*, SUM(p.money) total, MAX(p.date) last_activity
FROM test_users u
JOIN test_payments p
ON u.id= p.user_id
WHERE p.date BETWEEN CONVERT(datetime, '15.12.2012') AND CONVERT(datetime, '18.12.2012')
GROUP BY u.id, u.name
ORDER BY total DESC;
但是last_activity的结果是错误的,因为它也在日期范围内:
id name total last_activity
--------------------------------
2 peter 4.0000 2012-12-17
1 john 3.0000 2012-12-16
请提出解决方案。
答案 0 :(得分:3)
您需要将条件从where
子句移到case
语句:
SELECT u.id, u.name,
SUM(case when p.date BETWEEN CONVERT(datetime, '15.12.2012') AND CONVERT(datetime, '18.12.2012')
then p.money
end) total,
MAX(p.date) last_activity
FROM test_users u JOIN
test_payments p
ON u.id= p.user_id
GROUP BY u.id, u.name
ORDER BY total DESC;
如果您只想要在该期间内付款的用户,则可以添加:
having total is not null
如果希望NULL值显示为0而不是NULL,则在case语句中包含else 0
。
答案 1 :(得分:3)
在我工作的时候,看起来有几个其他的答案突然出现,但无论如何它在这里。这里有一个工作的sql小提琴:http://sqlfiddle.com/#!3/14808/6
基本上,无论日期范围如何,您都需要一个查询来提取最大日期。我选择将此作为相关子查询。
SELECT
u.id,
u.name,
SUM(IsNull(money,0)) as TotalMoneyInRange,
(SELECT max(date) FROM test_payments where user_id = u.id) AS LastPaymentOverAll
FROM test_users AS u
LEFT JOIN test_payments AS p
ON u.id = p.user_id
WHERE
p.date IS NULL OR
p.date between
CAST('12-11-2012' AS datetime) --range begin
and
CAST('12-16-2012' as datetime) --range end
GROUP BY u.id, u.name
答案 2 :(得分:1)
您还可以使用子查询来获得结果:
SELECT u.*, total, last_activity
FROM test_users u
JOIN
(
select sum(money) total, user_id
from test_payments
WHERE date BETWEEN CONVERT(datetime, '2012-12-15')
AND CONVERT(datetime, '2012-12-18')
group by user_id
) p
ON u.id= p.user_id
inner join
(
select user_id, max(date) last_activity
from test_payments
group by user_id
) p1
on p.user_id = p1.user_id
ORDER BY total DESC;
答案 3 :(得分:0)
您可以为没有WHERE子句的MAX日期添加子查询,如下所示:
SELECT
u.*
,SUM(p.money) total
,a.max_date last_activity
FROM test_users u
INNER JOIN test_payments p ON u.id = p.user_id
INNER JOIN (SELECT user_id, MAX(date) AS max_date
FROM test_payments
GROUP BY user_id) a ON u.id = a.user_id
WHERE p.date BETWEEN CONVERT(datetime, '15.12.2012') AND CONVERT(datetime, '18.12.2012')
GROUP BY u.id, u.name, a.max_date
ORDER BY total DESC;