【问题标题】:Postgres generate_seriesPostgres 生成系列
【发布时间】:2011-10-31 12:46:18
【问题描述】:

我想要对表格进行统计,为此我使用generate_series();

这是我正在做的:

SELECT x.month, amount
FROM (SELECT generate_series(
                 min(date_trunc('month', date)),
                 max(date_trunc('month', date)),
                 '1 month'
      ) AS month
      FROM table
      WHERE user_id = 55 AND ...
) x
LEFT JOIN (
      SELECT SUM(amount) AS amount, date_trunc('month', date) AS month
      FROM table
      WHERE user_id = 55 AND ...
      GROUP BY month
) q ON q.month = x.month
ORDER BY month

这很好用,但是当我想应用过滤器(例如获取特定用户的金额)时,我必须应用它们两次。有没有办法避免过滤两次,或者以更有效的方式重写它,因为我不确定这是否是正确的做法?

【问题讨论】:

    标签: sql postgresql generate-series


    【解决方案1】:

    您可以为此写WITH query

    WITH month_amount AS
    (
        SELECT
            sum(amount) AS amount,
            date_trunc('month', date) AS month
        FROM Amount
        WHERE user_id = 55 -- AND ...
        GROUP BY month
    )
    SELECT month, amount
    FROM
        (SELECT generate_series(min(month), max(month), '1 month') AS month
        FROM month_amount) x
    LEFT JOIN month_amount
    USING (month)
    ORDER BY month;
    

    示例结果:

    SELECT * FROM amount WHERE user_id = 55;
     amount_id | user_id | amount |    date    
    -----------+---------+--------+------------
             3 |      55 |      7 | 2011-03-16
             4 |      55 |      5 | 2011-03-22
             5 |      55 |      2 | 2011-05-07
             6 |      55 |     18 | 2011-05-27
             7 |      55 |      4 | 2011-06-14
    (5 rows)
    
    WITH month_amount ..
             month          | amount 
    ------------------------+--------
     2011-03-01 00:00:00+01 |     12
     2011-04-01 00:00:00+02 |       
     2011-05-01 00:00:00+02 |     20
     2011-06-01 00:00:00+02 |      4
    (4 rows)
    

    【讨论】:

    • 我从没想过 CTE,但它们真的很有用。非常感谢,它很完美。
    • +1 我学到了一些我不知道的关于 postgres 的东西 - 谢谢 :)
    • 如何生成系列,如 select m from generate_series(01,12) m output :01, 02 , 03 , 04, 05, 06, 07, 08 ,09, 10 ,11, 12跨度>
    【解决方案2】:

    您可以在 WITH 子句中执行查询,然后使用 SELECT 来添加缺失的月份:

    WITH query AS (
          SELECT SUM(amount) AS amount, date_trunc('month', date) AS month
          FROM table
          WHERE user_id = 55 AND ...
          GROUP BY month
    )
    SELECT date(d.month) AS month, q.amount
    FROM (
        SELECT generate_series(min(month), max(month), '1 month') AS month
        FROM query
        ) d
        LEFT JOIN query q ON q.month = d.month
    ORDER BY month
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-01
      • 2021-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-17
      相关资源
      最近更新 更多