2017-05-08 70 views
0

我有以下查詢來獲取每月累計用戶數:獲取累積月度用戶根據用戶的電子郵件數

SELECT RTRIM(TO_CHAR(DATE_TRUNC('month', created_at), 'Month YYYY')) AS month, 
     SUM(COUNT(id)::int) OVER (ORDER BY DATE_TRUNC('month', created_at)) AS total, 
     SUM((email  like '%@domain%')::int) AS with_domain, 
     SUM((email not like '%@domain%')::int) AS without_domain 
FROM users 
GROUP BY DATE_TRUNC('month', created_at) 
ORDER BY DATE_TRUNC('month', created_at); 

結果如下:

[ 
    {"month"=>"October 2015", "total"=>2, "with_domain"=>1, "without_domain"=>1}, 
    {"month"=>"December 2015", "total"=>6, "with_domain"=>4, "without_domain"=>0}, 
    {"month"=>"January 2016", "total"=>13, "with_domain"=>4, "without_domain"=>3}, 
    {"month"=>"February 2016", "total"=>15, "with_domain"=>2, "without_domain"=>0}, 
    {"month"=>"March  2016", "total"=>36, "with_domain"=>15, "without_domain"=>6}, 
] 

見,total怎麼算的累積和其他人不?

我嘗試以下查詢:

SELECT RTRIM(TO_CHAR(DATE_TRUNC('month', created_at), 'Month YYYY')) AS month, 
     SUM(COUNT(id)::int)     OVER (ORDER BY DATE_TRUNC('month', created_at)) AS total, 
     SUM((email  like '%@domain%')::int) OVER (ORDER BY DATE_TRUNC('month', created_at)) AS with_domain, 
     SUM((email not like '%@domain%')::int) OVER (ORDER BY DATE_TRUNC('month', created_at)) AS without_domain 
FROM users 
GROUP BY DATE_TRUNC('month', created_at) 
ORDER BY DATE_TRUNC('month', created_at); 

但它拋出

column "users.email" must appear in the GROUP BY clause or be used in an aggregate function LINE 3: SUM((email like '%@domain%')::int) OVER (ORDER BY...^: SELECT RTRI 

並添加emailGROUP BY條款是毫無意義可言......

如何使所有累計計數(就像total一樣)?

預期的結果是一樣

[ 
    {"month"=>"October 2015", "total"=>2, "with_domain"=>1, "without_domain"=>1}, 
    {"month"=>"December 2015", "total"=>6, "with_domain"=>5, "without_domain"=>1}, 
    {"month"=>"January 2016", "total"=>13, "with_domain"=>9, "without_domain"=>4}, 
    {"month"=>"February 2016", "total"=>15, "with_domain"=>11, "without_domain"=>4}, 
    {"month"=>"March  2016", "total"=>36, "with_domain"=>26, "without_domain"=>10}, 
] 
+0

你的錯誤是,你正試圖獲得'運行總量(電子郵件[不] LIKE「%@域% '):: int'而不是'SUM(email [not] like'%@ domain%'):: int)'。 –

回答

1

只是重複窗口子句爲每個要積累版本:

SELECT RTRIM(TO_CHAR(DATE_TRUNC('month', created_at), 'Month YYYY')) AS month, 
     SUM(COUNT(id)::int) OVER (ORDER BY DATE_TRUNC('month', created_at)) AS total, 
     SUM(SUM((email  like '%@domain%')::int)) OVER (ORDER BY DATE_TRUNC('month', created_at)) AS with_domain, 
     SUM(SUM((email not like '%@domain%')::int)) OVER (ORDER BY DATE_TRUNC('month', created_at)) AS without_domain 
FROM users 
GROUP BY DATE_TRUNC('month', created_at) 
ORDER BY DATE_TRUNC('month', created_at); 
+0

請問你,請告訴我如何清理這個以避免重複'(ORDER BY DATE_TRUNC('month',created_at)) '三次? –

+1

@AndreyDeineko [你可以命名你的窗口定義](https://www.postgresql.org/docs/current/static/sql-select.html#SQL-WINDOW)&使用'OVER window_name'語法。 – pozs

0

基於OP改寫評論

使用窗口函數與爲了休息AGGS爲好。同樣如果你使用相同的窗口,最好從這裏的主要部分取出它:

SELECT distinct RTRIM(TO_CHAR(DATE_TRUNC('month', created_at), 'Month YYYY')) AS month, 
     SUM(COUNT(id)::int) OVER w AS total, 
     SUM((email  like '%@domain%')::int) OVER w AS with_domain, 
     SUM((email not like '%@domain%')::int) OVER w AS without_domain 
     , DATE_TRUNC('month', created_at) --added for sorting 
FROM users 
WINDOW W AS (PARTITION BY DATE_TRUNC('month', created_at) ORDER BY DATE_TRUNC('month', created_at)) 
ORDER BY DATE_TRUNC('month', created_at); 
+0

我在我的問題中寫道,我嘗試過,並寫了一個錯誤,我得到。請再次過問這個問題 –

+0

我的查詢是不同的 - 它沒有分組。而且你可能會想要不同的 –

+0

是的 - 這意味着你需要用於排序的列也被選中。所以你要麼從訂單中刪除DATE_TRUNC('month',created_at)',要麼將其添加到列表中 –

1

首先得到每月的分組計數,然後得到運行總和。

SELECT month, 
     SUM(total) OVER (ORDER BY month) as total, 
     SUM(with_domain) OVER (ORDER BY month) AS with_domain, 
     SUM(without_domain) OVER (ORDER BY month) AS without_domain 
FROM (SELECT RTRIM(TO_CHAR(DATE_TRUNC('month', created_at), 'Month YYYY')) AS month, 
     COUNT(*) AS total, 
     SUM((email  like '%@domain%')::int) AS with_domain, 
     SUM((email not like '%@domain%')::int) AS without_domain 
     FROM users 
     GROUP BY RTRIM(TO_CHAR(DATE_TRUNC('month', created_at), 'Month YYYY')) 
     ) t 
ORDER BY month; 
+0

工作得很好,謝謝你的回答! –

相關問題