问题 如何在PostgreSQL中生成一个虚拟表来生成一系列日期?


我想生成一个日期列表,希望加入另一个表,但我不知道使用什么语法,类似于:

SELECT dates.date, transactions.account_id, transactions.amount
  FROM (...) as dates
       LEFT JOIN transactions ON transactions.date = dates.date
 WHERE dates.date >= '2010-01-01' AND dates.date <= '2010-12-31'
 ORDER BY dates.date;

我想要日期,所以我没有必要进一步按摩数据客户端。我用它来显示一个类似于这样的表:

Account    2010-01-01    2010-01-02    2010-01-03    Balance
============================================================
Chase 123        +100           -20           -70        +10
Chase 231                       +13            -9         +4

4479
2017-10-23 01:38


起源



答案:


日期列表

使用 generate_series函数 获取可添加到日期的数字列表,以获取日期列表:

SELECT CURRENT_DATE + s.a AS dates 
  FROM generate_series(0,14,7) as s(a);

结果:

dates
------------
2004-02-05
2004-02-12
2004-02-19

旋转

问题的后半部分涉及旋转结果集 - 将行数据转换为柱状数据。 PIVOT和UNPIVOT是ANSI,但我不认为它们是 目前由PostgreSQL支持。旋转查询最一致支持的方法是使用聚合函数:

   SELECT t.account,
          SUM(CASE WHEN t.date = '2010-01-01' THEN t.amount END) AS '2010-01-01',
          SUM(CASE WHEN t.date = '2010-01-02' THEN t.amount END) AS '2010-01-02',
          SUM(CASE WHEN t.date = '2010-01-03' THEN t.amount END) AS '2010-01-03',
          SUM(t.amount) AS Balance
     FROM (SELECT CURRENT_DATE + s.a AS dates 
             FROM generate_series(0,14,7) as s(a)) x
LEFT JOIN TRANSACTIONS y ON y.date = x.date
 GROUP BY t.account

动态列

...手段 动态SQL


11
2017-10-23 01:52



很棒的答案!感谢快速提示和指针。 - François Beausoleil
什么使用交叉表功能来转动? postgresql.org/docs/current/static/tablefunc.html - Kuberchaun
@ StarShip3000:是的,但它不是ANSI - OMG Ponies
从最好的我可以发现PIVOT和UNPIVOT不是sql-2003的ANSI的一部分。你能指点我说的话吗?我用了 savage.net.au/SQL 作为一个看的地方。 - Kuberchaun


答案:


日期列表

使用 generate_series函数 获取可添加到日期的数字列表,以获取日期列表:

SELECT CURRENT_DATE + s.a AS dates 
  FROM generate_series(0,14,7) as s(a);

结果:

dates
------------
2004-02-05
2004-02-12
2004-02-19

旋转

问题的后半部分涉及旋转结果集 - 将行数据转换为柱状数据。 PIVOT和UNPIVOT是ANSI,但我不认为它们是 目前由PostgreSQL支持。旋转查询最一致支持的方法是使用聚合函数:

   SELECT t.account,
          SUM(CASE WHEN t.date = '2010-01-01' THEN t.amount END) AS '2010-01-01',
          SUM(CASE WHEN t.date = '2010-01-02' THEN t.amount END) AS '2010-01-02',
          SUM(CASE WHEN t.date = '2010-01-03' THEN t.amount END) AS '2010-01-03',
          SUM(t.amount) AS Balance
     FROM (SELECT CURRENT_DATE + s.a AS dates 
             FROM generate_series(0,14,7) as s(a)) x
LEFT JOIN TRANSACTIONS y ON y.date = x.date
 GROUP BY t.account

动态列

...手段 动态SQL


11
2017-10-23 01:52



很棒的答案!感谢快速提示和指针。 - François Beausoleil
什么使用交叉表功能来转动? postgresql.org/docs/current/static/tablefunc.html - Kuberchaun
@ StarShip3000:是的,但它不是ANSI - OMG Ponies
从最好的我可以发现PIVOT和UNPIVOT不是sql-2003的ANSI的一部分。你能指点我说的话吗?我用了 savage.net.au/SQL 作为一个看的地方。 - Kuberchaun