【问题标题】:Create multiple rows for results in multiple days为多天的结果创建多行
【发布时间】:2018-10-11 13:01:37
【问题描述】:

我有一个简单的查询来返回计划文件中尚未结束的所有行。

SELECT [Run_ID]
      ,[ProductionLineID]
      ,[RecipeNR]
      ,[RecipeDesc]
      ,[StartTimeBakery]
      ,[EndTimeBakery]
      ,[ItemID]
      ,[ItemDesc]
      ,[Boxes]
      ,[Products_In_Box]
      ,[Products]
      ,[Pallets]
      ,[Boxes_On_Pallet]
      ,[AUD_Timestamp]
  FROM [PP_Planning].[dbo].[Planning]

  Where endTimeBakery > GETDATE()

  order by ProductionLineID, StartTimeBakery

简化样本结果:

StartTimeBakery           EndTimeBakery             Pallets
2018-10-12 03:00:00.000   2018-10-12 21:41:00.000   135
2018-10-12 22:00:00.000   2018-10-13 22:13:00.000   300
2018-10-13 23:59:00.000   2018-10-15 05:23:00.000   315

我正在寻找的是当 starttime-endtime 跨越一天以上时的自动拆分。

想要的输出:

StartTimeBakery           EndTimeBakery             Pallets
2018-10-12 03:00:00.000   2018-10-12 21:41:00.000   135,00
2018-10-12 22:00:00.000   2018-10-12 23:59:59.999   24,77
2018-10-13 00:00:00.000   2018-10-13 22:13:00.000   275,22
2018-10-13 23:59:00.000   2018-10-13 23:59:59.999   0,18
2018-10-14 00:00:00.000   2018-10-14 23:59:59.999   257,14
2018-10-15 00:00:00.000   2018-10-15 05:23:00.000   57,68

推理/逻辑 我希望能够显示每天生产(计划)的托盘数量。在上面想要的结果中,我取了原来的总量,然后除以开始和停止之间使用的时间,然后用它来分配每天计划的时间。

我不知道从哪里开始“拆分”这个。因此,我们将不胜感激。

【问题讨论】:

  • “拆分”是否仅限于两天以上?
  • 只要是多天,(2到x)

标签: sql sql-server split


【解决方案1】:

如果未指定日期范围,您可以使用递归来拆分源并获取计算比例所需的值。请参阅以下演示:

DECLARE @table TABLE (StartTimeBakery DATETIME2(3), EndTimeBakery DATETIME2(3), Pallets INT);
INSERT INTO @table VALUES ('2018-10-12 03:00:00.000','2018-10-12 21:41:00.000',135);
INSERT INTO @table VALUES ('2018-10-12 22:00:00.000','2018-10-13 22:13:00.000',300);
INSERT INTO @table VALUES ('2018-10-13 23:59:00.000','2018-10-15 05:23:00.000',315);

WITH Split AS
(
    SELECT *, 0 N, DATEDIFF(DAY, StartTimeBakery, EndTimeBakery) Diff FROM @table
    UNION ALL
    SELECT StartTimeBakery,EndTimeBakery,Pallets,N+1,Diff FROM Split WHERE N<Diff
), SplitDates AS
(
    SELECT
        StartTimeBakery,
        EndTimeBakery,
        Pallets,
        CASE WHEN N=0 THEN StartTimeBakery ELSE DATEADD(DAY,N, CAST(StartTimeBakery AS Date)) END MyStart,
        CASE WHEN N=Diff THEN EndTimeBakery ELSE DATEADD(MILLISECOND, -1, CAST(DATEADD(DAY,N+1, CAST(StartTimeBakery AS Date)) AS datetime2(3))) END MyEnd,
        N,
        Diff
    FROM Split
), Proportions AS
(
    SELECT *, DATEDIFF(millisecond, MyStart, MyEnd) ThisMs, SUM(DATEDIFF(millisecond, MyStart, MyEnd)) OVER (PARTITION BY StartTimeBakery) GroupMs
    FROM SplitDates
)
SELECT MyStart StartTimeBakery, MyEnd EndTimeBakery, CAST(1.0*Pallets*ThisMs/GroupMs as decimal(15,2)) Pallets
FROM Proportions
ORDER BY MyStart

结果

StartTimeBakery             EndTimeBakery               Pallets
--------------------------- --------------------------- ---------
2018-10-12 03:00:00.000     2018-10-12 21:41:00.000     135.00
2018-10-12 22:00:00.000     2018-10-12 23:59:59.999     24.78
2018-10-13 00:00:00.000     2018-10-13 22:13:00.000     275.22
2018-10-13 23:59:00.000     2018-10-13 23:59:59.999     0.18
2018-10-14 00:00:00.000     2018-10-14 23:59:59.999     257.14
2018-10-15 00:00:00.000     2018-10-15 05:23:00.000     57.68

【讨论】:

    【解决方案2】:

    这也可以通过递归 CTE 来完成

    示例 sn-p:

    declare @Table table (
     RunID int identity(1,1) primary key, 
     StartTimeBakery datetime, 
     EndTimeBakery datetime, 
     Pallets int
    );
    
    insert into @Table (StartTimeBakery, EndTimeBakery, Pallets) values
     (DATEADD(day,DATEDIFF(day,-1, GETDATE()),'03:00'), DATEADD(day,DATEDIFF(day,-1, GETDATE()),'21:41'), 135)
    ,(DATEADD(day,DATEDIFF(day,-1, GETDATE()),'22:00'), DATEADD(day,DATEDIFF(day,-2, GETDATE()),'22:13'), 300)
    ,(DATEADD(day,DATEDIFF(day,-2, GETDATE()),'23:59'), DATEADD(day,DATEDIFF(day,-4, GETDATE()),'05:23'), 315)
    ;
    
    
    with RCTE as
    (
        select 
        RunID, 
        StartTimeBakery as BaseStartTime, EndTimeBakery as BaseEndTime, Pallets as BasePallets,
        0 as Lvl, 
        StartTimeBakery as StartTime, 
        case 
        when cast(StartTimeBakery as date) =  cast(EndTimeBakery as date)
        then EndTimeBakery 
        else CONVERT(DATETIME,DATEADD(MILLISECOND, -10, DATEADD(DAY, 1, CONVERT(DATETIME2,CONVERT(DATE, StartTimeBakery))))) 
        end as EndTime, 
        Pallets
        from @Table
        where EndTimeBakery > GETDATE()
    
        union all
    
        select RunID, BaseStartTime, BaseEndTime, BasePallets,
        Lvl+1,
        CONVERT(DATETIME, DATEADD(DAY, 1, CONVERT(DATE,EndTime))),
        case when DATEADD(DAY, 1, EndTime) < BaseEndTime then DATEADD(DAY, 1, EndTime) else BaseEndTime end,
        Pallets
        from RCTE
        where EndTime < BaseEndTime
    )
    select 
    StartTime AS StartTimeBakery,
    EndTime AS EndTimeBakery,
    CAST(Pallets * (CAST(DATEDIFF(second, StartTime, EndTime) AS FLOAT) / DATEDIFF(second, BaseStartTime, BaseEndTime)) AS DECIMAL(10,2)) as PercDiffMinutes
    from RCTE
    order by BaseStartTime, StartTime;
    

    【讨论】:

      【解决方案3】:

      只有一次拆分(例如,最大延迟到第二天,您可以尝试类似

      WITH FORE as 
          (
          Select *, 
                 StartTimeBakery StartTime1, 
                 CASE WHEN CAST(EndTimeBakery as date) = CAST(StartTimeBakery as date) THEN 
                         EndTimeBakery 
                      ELSE DATEADD(ms,-1,CAST(CAST(EndTimeBakery as date) 
                                                           as datetime)) END AS EndTime1
          ),
          AFTER as
          (
          Select *, 
                CAST(CAST(EndTimeBakery as date) as datetime) StartTime1,
                EndTimeBakery EndTime1  
                          WHERE CAST(EndTimeBakery as date) = CAST(StartTimeBakery as date)
          ),
          SPLITS AS 
          (
                  SELECT * FROM FORE 
                    UNION ALL 
                     SELECT * FROM AFTER
          )
      
          SELECT * FROM SPLITS;
      

      所以解释一下,选择所有班次开始,结束时间限制在一天结束(如果班次结束,则更早) 然后再选择午夜运行的记录集,从 00:00 开始,到结束时间结束,然后将它们合并在一起。

      你如何选择在这些因素之间划分其他因素,你需要解决这个问题

      【讨论】:

        【解决方案4】:

        快速构建的东西,不是太花哨的 sql,但它可以工作。

            DECLARE @table TABLE (StartTime DATETIME, EndTime DATETIME, Qty INT)
        
        INSERT INTO @table VALUES ('2018-10-12 03:00:00.000','2018-10-12 21:41:00.000',135)
        INSERT INTO @table VALUES ('2018-10-12 22:00:00.000','2018-10-13 22:13:00.000',300)
        INSERT INTO @table VALUES ('2018-10-13 23:59:00.000','2018-10-15 05:23:00.000',315)
        
        SELECT StartTime, EndTime, Qty
          FROM @table
         WHERE DATEDIFF(DAY,StartTime,EndTime) = 0
        UNION ALL
        SELECT StartTime, DATEADD(SECOND,-1,DATEADD(dd,DATEDIFF(dd,0,StartTime)+1,0)), Qty*(CAST(DATEDIFF(SECOND,StartTime,DATEADD(SECOND,-1,DATEADD(dd,DATEDIFF(dd,0,StartTime)+1,0))) AS FLOAT)/CAST(DATEDIFF(SECOND,StartTime, EndTime) AS FLOAT))
          FROM @table
         WHERE DATEDIFF(DAY,StartTime,EndTime) <> 0
        UNION ALL
        SELECT DATEADD(dd,DATEDIFF(dd,0,EndTime),0), EndTime, Qty*(CAST(DATEDIFF(SECOND,DATEADD(dd,DATEDIFF(dd,0,EndTime),0),EndTime) AS FLOAT)/CAST(DATEDIFF(SECOND,StartTime, EndTime) AS FLOAT))
          FROM @table
         WHERE DATEDIFF(DAY,StartTime,EndTime) <> 0
        

        【讨论】:

          猜你喜欢
          • 2019-04-13
          • 1970-01-01
          • 1970-01-01
          • 2021-03-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多