使用序列顺序和按值分组的数据透视表

Pivot data with sequence order and group by values

在 SQL 服务器数据仓库 table 中,按给定详细信息的顺序查找 V、T、C group by Shipment_id order by TASK_SEQUENCE_NUMBER,其中 TASK_TYPE 的顺序是 V然后 T 然后 C.

如果V,T,C依次没有值,这个值可以为0 如果V,T,C不止一次,我们可以将值相加显示

下面是具有预期结果的 table 模式和数据,必须将其合并到 Task_Main Table.

中具有更多列的存储过程中
CREATE TABLE [dbo].[Task_Detail]
(
    [Task_Sid] [int] NULL,      
    [Shipment_ID] [decimal](18, 0) NULL,
    [TASK_SEQUENCE_No] [decimal](18, 0) NULL,
    [TASK_TYPE] [varchar](1) NULL,      
    [TASK_DURATION] [decimal](18, 0) NULL,      
    [LOCATION_CODE] [varchar](15) NULL,         
    [TaskStart] [bigint] NULL    
) ON [PRIMARY]

CREATE TABLE [dbo].[Task_Header]
(
    [Task_Sno] [int] NULL,      
    [Shipment_ID] [decimal](18, 0) NULL,
    [Vehicle_Id] [nchar](10) NULL,      
    [DepotVisitStartTime] [datetime2](7) NULL,      
    [Time_V] [bigint] NULL,         
    [Time_T] [bigint] NULL,     
    [Time_C] [bigint] NULL     
) ON [PRIMARY]


INSERT [dbo].[Task_Detail] ([Task_Sid], [Shipment_ID], [TASK_SEQUENCE_No], [TASK_TYPE], [TASK_DURATION], [LOCATION_CODE], [TaskStart]) 
VALUES (1, CAST(1 AS Decimal(18, 0)), CAST(1 AS Decimal(18, 0)), N'K', CAST(20 AS Decimal(18, 0)), N'LC39', 20),
       (2, CAST(1 AS Decimal(18, 0)), CAST(7 AS Decimal(18, 0)), N'L', CAST(21 AS Decimal(18, 0)), N'10019514', 21),
       (3, CAST(1 AS Decimal(18, 0)), CAST(3 AS Decimal(18, 0)), N'L', CAST(58 AS  Decimal(18, 0)), N'LC38', 58),
       (4, CAST(1 AS Decimal(18, 0)), CAST(6 AS Decimal(18, 0)), N'C', CAST(10 AS Decimal(18, 0)), NULL, 10),
       (5, CAST(1 AS Decimal(18, 0)), CAST(8 AS Decimal(18, 0)), N'V', CAST(30 AS Decimal(18, 0)), N'10019514', 30),
       (6, CAST(1 AS Decimal(18, 0)), CAST(10 AS Decimal(18, 0)), N'C', CAST(11 AS Decimal(18, 0)), N'RJC', 11),
       (7, CAST(1 AS Decimal(18, 0)), CAST(9 AS Decimal(18, 0)), N'T', CAST(19 AS Decimal(18, 0)), N'10019027', 19),
       (8, CAST(2 AS Decimal(18, 0)), CAST(7 AS Decimal(18, 0)), N'V', CAST(29 AS Decimal(18, 0)), N'10018952', 29),
       (9, CAST(2 AS Decimal(18, 0)), CAST(4 AS Decimal(18, 0)), N'K', CAST(20 AS Decimal(18, 0)), NULL, 20),
       (10, CAST(2 AS Decimal(18, 0)), CAST(5 AS Decimal(18, 0)), N'V', CAST(0 AS Decimal(18, 0)), N'302', 0),
       (11, CAST(3 AS Decimal(18, 0)), CAST(12 AS Decimal(18, 0)), N'T', CAST(19 AS Decimal(18, 0)), N'10019514', 19),
       (12, CAST(3 AS Decimal(18, 0)), CAST(13 AS Decimal(18, 0)), N'E', CAST(11 AS Decimal(18, 0)), N'10019514', 11),
       (13, CAST(2 AS Decimal(18, 0)), CAST(3 AS Decimal(18, 0)), N'V', CAST(32 AS Decimal(18, 0)), N'', 32),
       (14, CAST(3 AS Decimal(18, 0)), CAST(4 AS Decimal(18, 0)), N'K', CAST(20 AS Decimal(18, 0)), N'10018952', 20),
       (15, CAST(3 AS Decimal(18, 0)), CAST(5 AS Decimal(18, 0)), N'V', CAST(0 AS Decimal(18, 0)), N'LC57', 0),
       (16, CAST(3 AS Decimal(18, 0)), CAST(8 AS Decimal(18, 0)), N'T', CAST(19 AS Decimal(18, 0)), N'10019514', 19),
       (17, CAST(3 AS Decimal(18, 0)), CAST(9 AS Decimal(18, 0)), N'C', CAST(10 AS Decimal(18, 0)), N'10019027', 10),
       (18, CAST(3 AS Decimal(18, 0)), CAST(3 AS Decimal(18, 0)), N'L', CAST(21 AS Decimal(18, 0)), N'LC38', 21),
       (19, CAST(3 AS Decimal(18, 0)), CAST(11 AS Decimal(18, 0)), N'V', CAST(30 AS Decimal(18, 0)), N'10019514', 30),
       (20, CAST(3 AS Decimal(18, 0)), CAST(10 AS Decimal(18, 0)), N'L', CAST(21 AS Decimal(18, 0)), N'10019514', 21),
       (21, CAST(3 AS Decimal(18, 0)), CAST(1 AS Decimal(18, 0)), N'T', CAST(19 AS Decimal(18, 0)), N'LC39', 19),
       (22, CAST(3 AS Decimal(18, 0)), CAST(2 AS Decimal(18, 0)), N'C', CAST(10 AS Decimal(18, 0)), N'302', 10),
       (23, CAST(1 AS Decimal(18, 0)), CAST(2 AS Decimal(18, 0)), N'V', CAST(0 AS Decimal(18, 0)), N'302', 0),
       (24, CAST(1 AS Decimal(18, 0)), CAST(4 AS Decimal(18, 0)), N'V', CAST(29 AS Decimal(18, 0)), N'10018952', 29),
       (25, CAST(1 AS Decimal(18, 0)), CAST(5 AS Decimal(18, 0)), N'T', CAST(19 AS Decimal(18, 0)), N'LC57', 19)
, (26, CAST(3 AS Decimal(18, 0)), CAST(6 AS Decimal(18, 0)), N'L', CAST(58 AS Decimal(18, 0)), N'10019514', 58)
, (27, CAST(3 AS Decimal(18, 0)), CAST(7 AS Decimal(18, 0)), N'V', CAST(29 AS Decimal(18, 0)), N'10019514', 29)
, (28, CAST(2 AS Decimal(18, 0)), CAST(6 AS Decimal(18, 0)), N'L', CAST(58 AS Decimal(18, 0)), N'10018952', 58)
, (29, CAST(2 AS Decimal(18, 0)), CAST(2 AS Decimal(18, 0)), N'L', CAST(35 AS Decimal(18, 0)), NULL, 35)



INSERT [dbo].[Task_Header] ([Task_Sno], [Shipment_ID], [Vehicle_Id], [DepotVisitStartTime], [Time_V], [Time_T], [Time_C]) VALUES 
(1, CAST(1 AS Decimal(18, 0)), N'TN1       ', CAST(N'2019-02-15T07:25:33.0000000' AS DateTime2), NULL, NULL, NULL)
,(2, CAST(1 AS Decimal(18, 0)), N'TN1       ', CAST(N'2019-02-15T07:25:33.0000000' AS DateTime2), NULL, NULL, NULL)
,(3, CAST(1 AS Decimal(18, 0)), N'TN1       ', CAST(N'2019-02-15T07:25:33.0000000' AS DateTime2), NULL, NULL, NULL)
,(4, CAST(1 AS Decimal(18, 0)), N'TN1       ', CAST(N'2019-02-15T07:25:33.0000000' AS DateTime2), NULL, NULL, NULL)
,(5, CAST(2 AS Decimal(18, 0)), N'KA2       ', CAST(N'2019-02-15T06:12:52.0000000' AS DateTime2), NULL, NULL, NULL)
,(6, CAST(2 AS Decimal(18, 0)), N'KA2       ', CAST(N'2019-02-15T06:12:52.0000000' AS DateTime2), NULL, NULL, NULL)
,(7, CAST(3 AS Decimal(18, 0)), N'AP3       ', CAST(N'2019-02-15T06:32:52.0000000' AS DateTime2), NULL, NULL, NULL)
,(8, CAST(3 AS Decimal(18, 0)), N'AP3       ', CAST(N'2019-02-15T06:32:52.0000000' AS DateTime2), NULL, NULL, NULL)
,(9, CAST(3 AS Decimal(18, 0)), N'AP3       ', CAST(N'2019-02-15T13:12:21.0000000' AS DateTime2), NULL, NULL, NULL)

使用过滤器的预期结果:

按 Shipment_ID 排序数据,TASK_SEQUENCE_NUMBER 过滤器,其中 Location_code <> 'RJC' TaskMaster 和 TaskDetails 的连接是 Shipment_id TASK_TYPE 应该是给定序列中的 V,下一个是 T 的立即数,下一个是 C 的立即数,仅考虑用于输出

示例数据:结果 对于 Shipment_ID 1,我们有列 V : 59,它是给定 Shipment_Id 的 "V" 值的总和 结果数据按 shipment_id 分组,它是 [=42 的总和=] 4 和 8 = 29+30 = 59 T 列出现在 V 之后的序列中,它是 sequence_number 5 和 9 = 19 +19 = 38 的总和 C 列出现在 T 之后的序列中,它是 sequence_number 6 和 10 = 10 +11 = 21 的总和 对于发货 2,我们在 VTC Secquence 中没有任务类型 对于发货 3,我们在 V T C Secquence 中有 Task Type for no 7 ,8 , 9 值为 29 , 19, 10 这只有一次并且该值被发送到 main table

Expected Result
-----------------------------
Sno Shipment_ID Vehicle ID  DepotVisitStartTime         V   T   C
1   1           TN1         2019-02-15 07:25:33.0000000 59  38  21
2   1           TN1         2019-02-15 07:25:33.0000000 59  38  21
3   1           TN1         2019-02-15 07:25:33.0000000 59  38  21
4   1           TN1         2019-02-15 07:25:33.0000000 59  38  21
5   2           KA2         2019-02-15 06:12:52.0000000 0   0   0
6   2           KA2         2019-02-15 06:12:52.0000000 0   0   0
7   3           AP3         2019-02-15 06:32:52.0000000 29  19  10
8   3           AP3         2019-02-15 06:32:52.0000000 29  19  10
9   3           AP3         2019-02-15 13:12:21.0000000 29  19  10

这些列是下面 post 的延续,我想有一个存储过程将数据插入 Task_Master table [聚合日期和数量相同 table对于给定的 ID

如果您有SQL Server 2012+(我建议您这样做,2008 即将完全失去支持)那么您可以使用LEAD 实现这个:

WITH CTE AS(
    SELECT TD.Task_Sid,
           TD.Shipment_ID,
           TD.TASK_SEQUENCE_No,
           TD.TASK_TYPE,
           TD.TASK_DURATION,
           LEAD(TASK_TYPE,1) OVER (PARTITION BY Shipment_ID ORDER BY TASK_SEQUENCE_No) AS NextType,
           LEAD(TASK_DURATION,1) OVER (PARTITION BY Shipment_ID ORDER BY TASK_SEQUENCE_No) AS NextDuration,
           LEAD(TASK_TYPE,2) OVER (PARTITION BY Shipment_ID ORDER BY TASK_SEQUENCE_No) AS NextNextType,
           LEAD(TASK_DURATION,2) OVER (PARTITION BY Shipment_ID ORDER BY TASK_SEQUENCE_No) AS NextNextDuration
    FROM Task_Detail TD),
VTC AS(
    SELECT *
    FROM CTE
    WHERE TASK_TYPE = 'V'
      AND NextType = 'T'
      AND NextNextType = 'C'
)
SELECT TH.Task_Sno,
       TH.Shipment_ID,
       TH.Vehicle_Id,
       TH.DepotVisitStartTime,
       ISNULL(SUM(TASK_DURATION),0) AS V,
       ISNULL(SUM(NextDuration),0) AS T,
       ISNULL(SUM(NextNextDuration),0) AS C
FROM Task_Header TH
     LEFT JOIN VTC ON TH.Shipment_ID = VTC.Shipment_ID
GROUP BY TH.Task_Sno,
         TH.Shipment_ID,
         TH.Vehicle_Id,
         TH.DepotVisitStartTime;

如果没有,那么您需要对 table Task_Detail 进行 3 次扫描,这会花费更多:

WITH VTC AS(
    SELECT TD1.Task_Sid,
           TD1.Shipment_ID,
           TD1.TASK_SEQUENCE_No,
           TD1.TASK_TYPE,
           TD1.TASK_DURATION,
           TD2.TASK_TYPE AS NextType,
           TD2.TASK_DURATION  AS NextDuration,
           TD3.TASK_TYPE AS NextNextType,
           TD3.TASK_DURATION  AS NextNextDuration
    FROM Task_Detail TD1
         JOIN Task_Detail TD2 ON TD1.Shipment_ID = TD2.Shipment_ID
                             AND TD1.TASK_SEQUENCE_No +1 = TD2.TASK_SEQUENCE_No
         JOIN Task_Detail TD3 ON TD1.Shipment_ID = TD3.Shipment_ID
                             AND TD1.TASK_SEQUENCE_No +2 = TD3.TASK_SEQUENCE_No
    WHERE TD1.TASK_TYPE = 'V'
      AND TD2.TASK_TYPE = 'T'
      AND TD3.TASK_TYPE = 'C')
SELECT TH.Task_Sno,
       TH.Shipment_ID,
       TH.Vehicle_Id,
       TH.DepotVisitStartTime,
       ISNULL(SUM(TASK_DURATION),0) AS V,
       ISNULL(SUM(NextDuration),0) AS T,
       ISNULL(SUM(NextNextDuration),0) AS C
FROM Task_Header TH
     LEFT JOIN VTC ON TH.Shipment_ID = VTC.Shipment_ID
GROUP BY TH.Task_Sno,
         TH.Shipment_ID,
         TH.Vehicle_Id,
         TH.DepotVisitStartTime;

这会产生您想要的输出 select:

select h.*, coalesce(d.v, 0) as v,
       coalesce(d.t, 0) as t, coalesce(d.c, 0) as c
from task_header h outer apply
     (select sum(dv.task_duration) as v,
             sum(dt.task_duration) as t,
             sum(dc.task_duration) as c
      from task_detail dv join
           task_detail dt
           on dt.Shipment_ID = dv.Shipment_ID and dt.TASK_SEQUENCE_No = dv.TASK_SEQUENCE_No + 1 join
           task_detail dc
           on dc.Shipment_ID = dt.Shipment_ID and dc.TASK_SEQUENCE_No = dt.TASK_SEQUENCE_No + 1 
      where dv.Shipment_ID = h.Shipment_ID and dv.task_type = 'V' and dt.task_type = 'T' and dc.task_type = 'C'
     ) d;

这会更新:

update h
    set time_v = coalesce(d.v, 0),
        time_t = coalesce(d.t, 0),
        time_c = coalesce(d.c, 0)
from task_header h outer apply
     (select sum(dv.task_duration) as v,
             sum(dt.task_duration) as t,
             sum(dc.task_duration) as c
      from task_detail dv join
           task_detail dt
           on dt.Shipment_ID = dv.Shipment_ID and dt.TASK_SEQUENCE_No = dv.TASK_SEQUENCE_No + 1 join
           task_detail dc
           on dc.Shipment_ID = dt.Shipment_ID and dc.TASK_SEQUENCE_No = dt.TASK_SEQUENCE_No + 1 
      where dv.Shipment_ID = h.Shipment_ID and dv.task_type = 'V' and dt.task_type = 'T' and dc.task_type = 'C'
     ) d;

Here 是一个 db<>fiddle.