Создать несколько строк для результатов в несколько дней - PullRequest
0 голосов
/ 11 октября 2018

У меня есть простой запрос, чтобы вернуть все строки в файле планирования, которые еще не завершились.

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

Мне нужно автоматическое разделение, когда время начала и окончания превышает один день.

Требуемый выход:

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

Обоснование / логика Я хочу показать количество произведенных (запланированных) поддонов в день.В приведенном выше желаемом результате я взял исходную общую сумму и разделил ее на время, использованное между стартом и остановкой, и использовал его для распределения времени, запланированного на день.

Я не знаю, с чего начать 'разделить это.Так что любая помощь приветствуется.

Ответы [ 4 ]

0 голосов
/ 11 октября 2018

Это также можно сделать с помощью рекурсивного CTE

Пример фрагмента:

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;
0 голосов
/ 11 октября 2018

Что-то быстро построить, не слишком сложный 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
0 голосов
/ 11 октября 2018

Если диапазоны дат не указаны, вы можете использовать рекурсию для разделения источника и получения значений, необходимых для вычисления пропорций.Смотрите следующую демонстрацию:

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
0 голосов
/ 11 октября 2018

только для одного разделения (например, максимальный переход на следующий день, вы можете попробовать что-то вроде

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 и заканчивающимся в время окончания, затем объедините их вместе.

Как вы решили разделить другие факторы междус этим вам нужно разобраться

...