簡體   English   中英

Postgres:數天

[英]Postgres: Count over a series of days

我創建了以下查詢,該查詢返回1天的3個值('20170731')。 我想弄清楚的是,如何從30天前到現在的60天每天連續運行此查詢,並每天返回一行。

SELECT DATE_TRUNC('day', '20170731'::TIMESTAMP),
       COUNT(CASE WHEN state NOT IN ('unsub','skipped', 'error') THEN 1 ELSE NULL END) AS a,
       COUNT(CASE WHEN (state IN ('unsub')) AND (DATE_TRUNC('month', unsub_at) BETWEEN '20170731' AND DATE_TRUNC('day', NOW()))  THEN 1 ELSE NULL END) AS b,
       COUNT(CASE WHEN (state IN ('skipped')) AND (DATE_TRUNC('month', skipped_at) BETWEEN '20170731' AND DATE_TRUNC('day', NOW()))  THEN 1 ELSE NULL END) AS c          
FROM subscriptions
WHERE DATE_TRUNC('day', run) >= '20170731'
      AND DATE_TRUNC('day', created_at) <= '20170731'
ORDER BY 1

您可以使用generate_series()生成日期。 這個想法是:

SELECT gs.dte,
       SUM( (state NOT IN ('unsub','skipped', 'error'))::int) AS a,
       SUM( (state IN ('unsub') AND DATE_TRUNC('month', unsub_at) BETWEEN gs.dte AND DATE_TRUNC('day', NOW()))::int) AS b,
       SUM( (state IN ('skipped') AND DATE_TRUNC('month', skipped_at) BETWEEN gs.dte AND DATE_TRUNC('day', NOW()))::int) AS c          
FROM subscriptions s CROSS JOIN
     generate_series(current_date - interval '30 day',
                     current_date + interval '60 day',
                     interval '1 day'
                    ) gs(dte)
WHERE DATE_TRUNC('day', run) >= gs.dte AND
      DATE_TRUNC('day', created_at) <= gs.dte
GROUP BY gs.dte
ORDER BY 1;

我切換查詢以將布爾值轉換為整數-我只是覺得更容易理解。

請參閱設置返回函數 您想要的是generate_series函數。

首先檢查一下,以了解其作用:

SELECT
    *
FROM
    generate_series(
        '2017-07-31'::TIMESTAMP - INTERVAL '30 days', 
        '2017-07-31'::TIMESTAMP + INTERVAL '60 days', 
        INTERVAL '1 day');

然后您的查詢可能看起來像這樣:

SELECT DATE_TRUNC('day', stamp),
       COUNT(CASE WHEN state NOT IN ('unsub','skipped', 'error') THEN 1 ELSE NULL END) AS a,
       COUNT(CASE WHEN (state IN ('unsub')) AND (DATE_TRUNC('month', unsub_at) BETWEEN '20170731' AND DATE_TRUNC('day', NOW()))  THEN 1 ELSE NULL END) AS b,
       COUNT(CASE WHEN (state IN ('skipped')) AND (DATE_TRUNC('month', skipped_at) BETWEEN stamp AND DATE_TRUNC('day', NOW()))  THEN 1 ELSE NULL END) AS c          
FROM subscriptions,
     generate_series('2017-07-31'::TIMESTAMP - INTERVAL '30 days', '2017-07-31'::TIMESTAMP + INTERVAL '60 days', INTERVAL '1 day') AS stamp
WHERE DATE_TRUNC('day', run) >= stamp
      AND DATE_TRUNC('day', created_at) <= stamp
ORDER BY 1

只需添加generate_series函數,就像使用普通輸入表(別名為AS stamp ),使用subscriptions (笛卡爾積) JOINJOIN )並使用stamp值而不是硬編碼的'20170731'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM