【问题标题】:Replace NULL values per partition替换每个分区的 NULL 值
【发布时间】:2021-07-04 12:08:26
【问题描述】:

我想为每个session_iddevice 列中的NULL 值填充一个关联的非NULL 值。我怎样才能做到这一点?

这里是示例数据:

+------------+-------+---------+
| session_id | step  | device  |
+------------+-------+---------+
| 351acc     | step1 |         |
| 351acc     | step2 |         |
| 351acc     | step3 | mobile  |
| 351acc     | step4 | mobile  |
| 350bca     | step1 | desktop |
| 350bca     | step2 |         |
| 350bca     | step3 |         |
| 350bca     | step4 | desktop |
+------------+-------+---------+

期望的输出:

+------------+-------+---------+
| session_id | step  | device  |
+------------+-------+---------+
| 351acc     | step1 | mobile  |
| 351acc     | step2 | mobile  |
| 351acc     | step3 | mobile  |
| 351acc     | step4 | mobile  |
| 350bca     | step1 | desktop |
| 350bca     | step2 | desktop |
| 350bca     | step3 | desktop |
| 350bca     | step4 | desktop |
+------------+-------+---------+

【问题讨论】:

    标签: sql postgresql null window-functions coalesce


    【解决方案1】:

    正确排序的window function first_value() 可能最便宜:

    SELECT session_id, step
         , COALESCE(device
                  , first_value(device) OVER (PARTITION BY session_id ORDER BY device IS NULL, step)
                   ) AS device
    FROM   tbl
    ORDER  BY session_id DESC, step;
    

    db小提琴here

    ORDER BY device IS NULL, stepNULL 值排序在最后,因此选择最早的具有非空值的step。见:

    如果session_id 的 notnull 设备始终相同,您可以简化为仅ORDER BY device IS NULL。而且你不需要COALESCE

    【讨论】:

      【解决方案2】:

      根据您的数据示例,每个会话有一个设备,因此您只需添加一个子查询即可从其他行获取值

      WITH j (session_id, step, device) AS (
        VALUES ('351acc','step1',NULL),
               ('351acc','step2',NULL),
               ('351acc','step3','mobile'),
               ('351acc','step4','mobile'),
               ('350bca','step1','desktop'),
               ('350bca','step2',NULL),
               ('350bca','step3',NULL),
               ('350bca','step4','desktop')
      ) 
      SELECT session_id,step,
        (SELECT DISTINCT device 
         FROM j q2
         WHERE q2.session_id = q1.session_id AND q2.device IS NOT NULL) AS device
      FROM j q1 ORDER BY session_id,step;
      
       session_id | step  | device  
      ------------+-------+---------
       350bca     | step1 | desktop
       350bca     | step2 | desktop
       350bca     | step3 | desktop
       350bca     | step4 | desktop
       351acc     | step1 | mobile
       351acc     | step2 | mobile
       351acc     | step3 | mobile
       351acc     | step4 | mobile
      (8 Zeilen)
      

      演示:db<>fiddle

      【讨论】:

        【解决方案3】:
        select session_id, step,coalesce(device, max(device) over (partition by session_id order by step desc)) device
        from table 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-01
          • 2020-08-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多