我的核心表数据如下所示。它正在跟踪订单状态。
身份证 | 零件编号 | 已进入 | 选择时间 | 交货时间 |
---|---|---|---|---|
100 | 50A | 2024-03-28 08:59:13.727 | 2024-03-28 09:30:20.237 | 2024-03-28 09:56:42.570 |
125 | 60B | 2024-03-28 08:59:22.290 | 2024-03-28 09:31:32.543 | 2024-03-28 09:56:50.683 |
171 | 50A | 2024-03-28 14:31:28.480 | 空 | 空 |
211 | 70B | 2024-03-28 14:31:33.613 | 空 | 空 |
我需要编写一个查询将其转换为这种格式:
t_邮票 | 50A_100 | 60B_125 | 50A_171 | 70B_211 |
---|---|---|---|---|
2024-03-28 08:59:13.727 | 已输入 | 空 | 空 | 空 |
2024-03-28 08:59:22.290 | 空 | 已输入 | 空 | 空 |
2024-03-28 09:30:20.237 | 已挑选 | 空 | 空 | 空 |
2024-03-28 09:31:32.543 | 空 | 已挑选 | 空 | 空 |
2024-03-28 09:56:42.570 | 已交付 | 空 | 空 | 空 |
2024-03-28 09:56:50.683 | 空 | 已交付 | 空 | 空 |
2024-03-28 14:31:28.480 | 空 | 空 | 已输入 | 空 |
2024-03-28 14:31:33.613 | 空 | 空 | 空 | 已输入 |
换句话说,我需要创建一个
t_stamp
列,其中包含原始表中的每个时间戳。我需要为每个 ID 指定一个名为 [PartNum]_[ID]
的列。我需要根据原始时间戳来自的列返回 ENTERED、PICKED 或 DELIVERED。如果 t_stamp 与给定列中的任何信息都不对应,我只需返回 null。据我所知,如果源数据中有大量 ID,并且有大量空值,将会有大量列。
这就是我所得到的。我可以通过将其放入
WHERE
子句来手动获取每个 ID 所需的数据,但我不知道如何使用 PIVOT
来获取每个 ID + PartNum 组合的列。 PIVOT
是否是合适的工具?
Select B.*
From MyTable A
CROSS APPLY (VALUES (EnteredOn,'ENTERED')
,(PickedTime,'PICKED')
,(DeliveredTime,'DELIVERED')
) B(t_stamp,[Status])
WHERE ID = 100
ORDER BY t_stamp ASC
该查询返回这些结果。如何将每个 ID(来自上面的原始结果)合并到其自己的列中并如上所述插入空值?
t_邮票 | 状态 |
---|---|
2024-03-28 08:59:13.727 | 已输入 |
2024-03-28 09:30:20.237 | 已挑选 |
2024-03-28 09:56:42.570 | 已交付 |
数据
CREATE TABLE mytable(
ID INTEGER NOT NULL
,PartNum VARCHAR(40) NOT NULL
,EnteredOn VARCHAR(40) NOT NULL
,PickedTime VARCHAR(40)
,DeliveredTime VARCHAR(40)
);
INSERT INTO mytable(ID,PartNum,EnteredOn,PickedTime,DeliveredTime) VALUES
(100,'50A','2024-03-28 08:59:13.727','2024-03-28 09:30:20.237','2024-03-28 09:56:42.570'),
(125,'60B','2024-03-28 08:59:22.290','2024-03-28 09:31:32.543','2024-03-28 09:56:50.683'),
(171,'50A','2024-03-28 14:31:28.480',NULL,NULL),
(211,'70B','2024-03-28 14:31:33.613',NULL,NULL);
同时使用逆透视和透视
select *
from
(
select CONCAT(PartNum,'_',ID) COL
,st,
t_stamp
from (select ID,PartNum,
EnteredOn as Entered,
PickedTime as Picked,
DeliveredTime as Delivered
from mytable) m
unpivot
(
t_stamp
for st in ([Entered]
,[Picked]
,[Delivered]
)
) unpiv
) src
pivot
(
max(st)
for COL in ([50A_100], [60B_125], [50A_171],[70B_211])
) piv;
类似这样的:
SELECT t_stamp
, max(CASE WHEN partnum = '50A' AND id = 100 THEN Status END) AS [50A_100]
, max(CASE WHEN partnum = '60B' AND id = 125 THEN Status END) AS [60B_125]
, max(CASE WHEN partnum = '50A' AND id = 171 THEN Status END) AS [50A_171]
, max(CASE WHEN partnum = '70B' AND id = 211 THEN Status END) AS [70B_211]
FROM
(
VALUES (100, N'50A', N'2024-03-28 08:59:13.727', N'2024-03-28 09:30:20.237', N'2024-03-28 09:56:42.570')
, (125, N'60B', N'2024-03-28 08:59:22.290', N'2024-03-28 09:31:32.543', N'2024-03-28 09:56:50.683')
, (171, N'50A', N'2024-03-28 14:31:28.480', NULL, NULL)
, (211, N'70B', N'2024-03-28 14:31:33.613', NULL, NULL)
) t (ID,PartNum,EnteredOn,PickedTime,DeliveredTime)
CROSS APPLY (VALUES (EnteredOn,'ENTERED')
,(PickedTime,'PICKED')
,(DeliveredTime,'DELIVERED')
) B(t_stamp,[Status])
WHERE t_stamp IS NOT NULL
GROUP BY t_stamp
这只是一个普通的条件聚合,其中 MAX(CASE WHEN) 为您感兴趣的每个部分创建列。