我有一个简单的查询,以返回计划文件中尚未结束的所有行。
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
推理/逻辑 我希望能够显示每天生产(计划)的托盘数量。在上面想要的结果中,我已将原始总金额除以开始和停止之间使用的时间,然后将其分配给每天计划的时间。
我不知道从哪里开始“拆分”。因此,我们将不胜感激。
答案 0 :(得分: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
答案 1 :(得分:1)
这也可以通过递归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;
答案 2 :(得分:0)
仅进行一次拆分(例如,第二天的最大超车期,您可以尝试类似
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开始,在结束时间结束,然后将它们合并在一起。
如何选择在这些因素之间分配其他因素,您需要解决
答案 3 :(得分:0)
快速构建的东西,虽然不是很花哨的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