2013-10-25 59 views
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架構和數據

我怎樣才能做到這一點?

回答

2

爲此,我們需要篩選select而不是連接上的數據。

刪除此條件:

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

+0

mysql錯誤,有什麼想法爲什麼? – greenbandit

+0

你可以在這裏複製整個查詢和你得到的錯誤嗎? – Yochai

+0

這裏是模式http://sqlfiddle.com/#!2/20a974/2 – greenbandit

0

您可以進行另一次捐贈,給它一個不同的別名:LEFT JOIN donation 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 
+0

喜,請更具體 – greenbandit

+0

我很快補充一個例子,試圖澄清我的意思。在平板電腦上輸入代碼並不容易,儘管如此,當我再次訪問筆記本電腦時,我會刷新它。 – CompuChip

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說,這是清潔劑剛剛加入到捐款表兩次,但我有我的加入邏輯出事了約翰的值越來越重複。我認爲這需要一個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