【问题标题】:Generate date series for each id为每个 id 生成日期系列
【发布时间】:2021-06-01 06:24:15
【问题描述】:

我有一个有四列的表。我想为从date1date3 的每个id 创建一个间隔为1 天的日期列。如果没有date3,那么直到date2,如果没有date2,那么只有date1

如何在 Postgres 中实现这一点?谢谢!

样本数据:

+-------+---------------------+---------------------+---------------------+
|  id   |        date1        |        date2        |        date3        |
+-------+---------------------+---------------------+---------------------+
| 76efg | 2021-01-03 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03 |
| b67cs | 2021-01-09 03:45:24 | 2021-01-14 06:55:13 |                     |
| fsf56 | 2021-01-25 11:18:03 | 2021-01-25 11:18:03 |                     |
| ghl56 | 2021-01-29 14:25:57 | 2021-02-02 17:37:10 | 2021-02-18 01:13:37 |
| 90tum | 2021-02-18 06:13:30 |                     |                     |
+-------+---------------------+---------------------+---------------------+

id '76efg' 的期望输出:

+-------+--------------+---------------------+---------------------+---------------------+--+
|  id   | date_created |        date1        |        date2        |        date3        |  |
+-------+--------------+---------------------+---------------------+---------------------+--+
| 76efg | 2021-01-03   | 2021-01-03 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03 |  |
| 76efg | 2021-01-04   | 2021-01-03 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03 |  |
| 76efg | 2021-01-05   | 2021-01-03 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03 |  |
| 76efg | 2021-01-06   | 2021-01-03 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03 |  |
| 76efg | 2021-01-07   | 2021-01-03 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03 |  |
| 76efg | 2021-01-08   | 2021-01-03 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03 |  |
+-------+--------------+---------------------+---------------------+---------------------+--+

【问题讨论】:

    标签: sql postgresql generate-series


    【解决方案1】:

    您是否尝试过使用generated_series()?以下查询基于date1date2date3 生成一系列时间戳,以及使用COALESCE 找到的系列的限制 - 基本上检查列是否为null

    WITH j (id,date1,date2,date3) AS (
      VALUES ('76efg',
              '2021-01-03 06:33:54'::TIMESTAMP,
              '2021-01-07 05:19:03'::TIMESTAMP,
              '2021-01-08 05:19:03'::TIMESTAMP ),
             ('b67cs',
             '2021-01-09 03:45:24'::TIMESTAMP,
             '2021-01-14 06:55:13'::TIMESTAMP,
             NULL),
             ('90tum','2021-02-18 06:13:30'::TIMESTAMP,
             NULL,NULL)
    )
    SELECT 
      id,
      generate_series(
        date1,
        COALESCE(date3,date2,date1),'1 day'::INTERVAL) AS date_created,
      date2,
      date3
    FROM j;
    
      id   |    date_created     |        date2        |        date3        
    -------+---------------------+---------------------+---------------------
     76efg | 2021-01-03 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03
     76efg | 2021-01-04 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03
     76efg | 2021-01-05 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03
     76efg | 2021-01-06 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03
     76efg | 2021-01-07 06:33:54 | 2021-01-07 05:19:03 | 2021-01-08 05:19:03
     b67cs | 2021-01-09 03:45:24 | 2021-01-14 06:55:13 | 
     b67cs | 2021-01-10 03:45:24 | 2021-01-14 06:55:13 | 
     b67cs | 2021-01-11 03:45:24 | 2021-01-14 06:55:13 | 
     b67cs | 2021-01-12 03:45:24 | 2021-01-14 06:55:13 | 
     b67cs | 2021-01-13 03:45:24 | 2021-01-14 06:55:13 | 
     b67cs | 2021-01-14 03:45:24 | 2021-01-14 06:55:13 | 
     90tum | 2021-02-18 06:13:30 |                     | 
    

    检查这个db<>fiddle

    感谢@clamp 关于COALESCE的提示:

    COALESCE(COALESCE(date3,date2),date1) 等价于 COALESCE(date3,date2,date1)

    【讨论】:

    • COALESCE(COALESCE(date3,date2),date1) 等价于COALESCE(date3,date2,date1)
    • @clamp 太棒了,我不知道!感谢您的提示:)
    猜你喜欢
    • 2021-02-13
    • 2019-08-14
    • 2011-05-27
    • 2016-07-02
    • 2021-12-19
    • 1970-01-01
    • 2021-10-28
    • 2019-04-13
    相关资源
    最近更新 更多