0

需要一些帮助来构建查询,这是我目前的方案:

users:
+----+------------+
| id |  username  |
+----+------------+
| 1  |    rob     |
| 2  |    john    |
| 3  |    jane    | <--- jane never has donated
| 4  |    mike    | 
+----+------------+

donations:
+--------------------+------------+
|   uid   |  amount  |   date     |
+---------+----------+------------+
|    1    |    20    | 2013-10-10 | 
|    2    |    5     | 2013-10-03 | 
|    2    |    50    | 2013-09-25 |
|    2    |    5     | 2013-10-01 |
|    4    |    100   | 2012-10-01 | <-- past year
+---------+----------+------------+


Result I want:
+---------+-------------+---------+-------------+---------------+----------+ 
|    id   |   username  | amount  |   monthly   |  totalamount  |   total  |
+---------+-------------+---------+-------------+ --------------+----------+
|    1    |     rob     |   20    |      1      |       20      |     1    |
|    2    |     john    |   60    |      3      |       60      |     3    |
|    3    |     jane    |   0     |      0      |       0       |     0    |
|    4    |     mike    |   0     |      0      |       100     |     1    | 
+---------+-------------+-----------------------+---------------+----------+

这是我的查询:

SELECT
  u.*,
  COALESCE(sum(d.amount), 0) amount,
  COUNT(d.uid) monthly, 
  COUNT(d.amount) as Total, <-- need to get sum all time donations and number of times donated
FROM users u
LEFT JOIN donations d
  ON u.id = d.uid
    AND (month(d.date), year(d.date)) = (month(CURDATE()), year(CURDATE()))
GROUP BY u.id ORDER BY u.id ASC

所以我需要从相同的数据中添加 2 个不同的总和。

编辑:http ://sqlfiddle.com/#!2/20a974/9架构和数据

我怎么能做到这一点?

4

3 回答 3

2

为此,我们需要过滤 select 上的数据,而不是 join 上的数据。

删除此条件:

AND (month(d.date), year(d.date)) = (month(CURDATE()), year(CURDATE()))

并将其添加到选择中:

SUM (CASE WHEN (month(d.date), year(d.date)) = (month(CURDATE()), year(CURDATE())) THEN 1 ELSE 0 END) as monthly

编辑:

整个查询:

SELECT users.id, users.username, 
  COALESCE(sum(CASE WHEN (month(donations.date), year(donations.date)) = (month(CURDATE()), year(CURDATE())) THEN donations.amount ELSE 0 END), 0) monthly_sum, 
  COALESCE(sum(CASE WHEN (month(donations.date), year(donations.date)) = (month(CURDATE()), year(CURDATE())) THEN 1 ELSE 0 END), 0) monthly_amount, 

  COALESCE(sum(donations.amount), 0) total_sum, 
  count(*) total_amount

from users
left join donations
  on donations.uid = users.id
group by users.id, users.username

http://sqlfiddle.com/#!2/20a974/20/0

于 2013-10-25T22:14:22.243 回答
1

对我来说,考虑单独分组信息的最简单方法是将其放入单独的查询中,然后将结果重新组合在一起。这可能不是最有效的,但它有助于使某些东西发挥作用。

select auo.id, auo.username, 
  coalesce(monthly_count, 0), coalesce(monthly_total, 0),
  coalesce(total, 0), coalesce(total_amount, 0)
from aaa_users auo
left join  (
   select au.id as id, count(adm.amount) as monthly_count, SUM(adm.amount) as monthly_total
   from aaa_users au join aaa_donations adm on au.id = adm.uid and adm.donate_date > GETDATE()-30
   group by au.id
) as monthly on monthly.id = auo.id
left join (
   select au.id as id, count(ady.amount) total, SUM(ady.amount) as total_amount
   from aaa_users au join aaa_donations ady on au.id = ady.uid and ady.donate_date >  getDate()-450
   group by au.id 
) as yearly on yearly.id = auo.id

正如@CompuChip 所说,加入捐赠表两次更干净,但我的加入逻辑有问题,因为 john 的值被重复了。我认为需要有一个donations.id 列来防止合并每月和总捐款。无论如何,这是一个示例,即使它无法正常工作

select au.id, au.username, 
    count(adm.amount), SUM(adm.amount) as monthly_total, 
    count(ady.amount), SUM(ady.amount) as total_amount
from aaa_users au 
left outer join aaa_donations adm on au.id = adm.uid and adm.donate_date > GETDATE()-60
left outer join aaa_donations ady on au.id = ady.uid and ady.donate_date > getDate()-450
group by au.id, au.username
order by au.id, au.username
于 2013-10-25T22:47:24.760 回答
0

您可以对捐赠进行另一次联接,给它一个不同的别名:LEFT JOINdonations d2 on d2.uid = u.id。然后将最后两个字段的 d2.amount 相加,例如

SELECT u.*, 
  COALESCE(sum(d.amount), 0) amount, 
  COUNT(d.uid) monthly, 
  COUNT(d.amount) as Total, 

  COALESCE(sum(d2.amount), 0) amountAll, 
  COUNT(d2.uid) monthlyAll,
  COUNT(d2.amount) as TotalAll

  FROM users u
     LEFT JOIN donations d ON u.id = d.uid AND (month(d.date), year(d.date)) = (month(CURDATE()), year(CURDATE()))
     LEFT JOIN donations d2 ON u.id = d2.uid 

 GROUP BY u.id ORDER BY u.id ASC
于 2013-10-25T21:59:41.913 回答