基于Shift分区,根据Sort cart的Dept生成Shift_loc列的SQL实现
问题:为工人动作表新增Shift_loc列
现有一张记录工人动作的表,包含action_ID、action_name、Action_DTTM、Dept、Shift_ID字段。需要新增Shift_loc列,该列的值需根据每个Shift_ID分区内,Action_Name为Sort cart的记录对应的Dept值来确定。
原始表数据
| Action_ID | Action_Name | Action_DTTM | Dept | Shift_ID |
|---|---|---|---|---|
| 1 | Load cart | 11/01/2023 14:12:01 | NULL | 1 |
| 2 | Sort cart | 11/01/2023 16:12:23 | Magenta | 1 |
| 3 | Distribute | 11/01/2023 16:17:14 | M | 1 |
| 4 | Load cart | 11/04/2023 11:12:51 | NULL | 2 |
| 5 | Sort cart | 11/04/2023 11:22:01 | Blue | 2 |
| 6 | Distribute | 11/04/2023 12:12:35 | B | 2 |
| 7 | Load cart | 11/05/2023 06:22:17 | NULL | 3 |
| 8 | Sort cart | 11/05/2023 08:19:21 | Magenta | 3 |
| 9 | Distribute | 11/05/2023 14:12:01 | M | 3 |
期望输出
| Action_ID | Action_Name | Action_DTTM | Dept | Shift_ID | Shift_loc |
|---|---|---|---|---|---|
| 1 | Load cart | 11/01/2023 14:12:01 | NULL | 1 | Magenta |
| 2 | Sort cart | 11/01/2023 16:12:23 | Magenta | 1 | Magenta |
| 3 | Distribute | 11/01/2023 16:17:14 | M | 1 | Magenta |
| 4 | Load cart | 11/04/2023 11:12:51 | NULL | 2 | Blue |
| 5 | Sort cart | 11/04/2023 11:22:01 | Blue | 2 | Blue |
| 6 | Distribute | 11/04/2023 12:12:35 | B | 2 | Blue |
| 7 | Load cart | 11/05/2023 06:22:17 | NULL | 3 | Magenta |
| 8 | Sort cart | 11/05/2023 08:19:21 | Magenta | 3 | Magenta |
| 9 | Distribute | 11/05/2023 14:12:01 | M | 3 | Magenta |
用户尝试过CASE表达式但不知道如何在Shift分区内结合两列赋值,也考虑过FIRST_VALUE函数但不清楚如何定位分区内有效Dept值。
解决方案
方法1:使用MAX()结合窗口函数
利用每个Shift_ID分区内Sort cart对应的Dept是唯一值的特点,用MAX()聚合并按Shift_ID分区,直接提取该值作为Shift_loc:
SELECT Action_ID, Action_Name, Action_DTTM, Dept, Shift_ID, MAX(CASE WHEN Action_Name = 'Sort cart' THEN Dept END) OVER (PARTITION BY Shift_ID) AS Shift_loc FROM worker_actions;
原理:CASE表达式仅在Action_Name为Sort cart时返回对应的Dept,否则返回NULL;窗口函数按Shift_ID分区后,MAX会忽略NULL,直接取分区内唯一的有效Dept值,赋值给该分区所有行。
方法2:使用FIRST_VALUE()结合条件排序
通过排序让Sort cart的记录排在分区最前面,再用FIRST_VALUE()提取对应Dept:
SELECT Action_ID, Action_Name, Action_DTTM, Dept, Shift_ID, FIRST_VALUE(Dept) OVER ( PARTITION BY Shift_ID ORDER BY CASE WHEN Action_Name = 'Sort cart' THEN 0 ELSE 1 END ) AS Shift_loc FROM worker_actions;
原理:排序条件将Sort cart的记录优先级设为0(排在最前),其他记录为1;FIRST_VALUE()会提取分区内第一行的Dept值,也就是Sort cart对应的Dept,赋值给该分区所有行。
如果每个Shift_ID内可能有多条Sort cart记录且Dept一致,两种方法都适用;若存在多值,可根据需求调整聚合函数(比如取最新时间的Dept,此时需结合Action_DTTM排序)。
内容的提问来源于stack exchange,提问作者crackersNcheese
相关产品推荐
相关产品推荐

