我遇到了SQL问题。我有一个查询,它创建一个临时表,用其他几个表中的数据填充它,进行一些计算和更新,并将这些数据提供给应用程序。最后一步是计算两个日期时间之间的小时数和分钟数,但它们应分为dayHours,dayMins,nightHours,nightMins(日期时间可以是20天以上)。以下要点将可视化我想要做的事情:
DateTime1 = 20-04-2016 13:30
。 DateTime2 = 21-04-2016 07:15
。我正在提供create table
查询,但我只需要计算方面的帮助,因此您可以忽略我的表和数据。请注意,我删除了几乎所有格式以减少,因为帖子很长。
CREATE TABLE [dbo].[myTestTable](
[JHID] [int] NULL, [ToDateTime] [datetime] NULL,
[startPayDateTime] [datetime] NULL, [opDayHour] [int] NULL,
[opDayMin] [int] NULL, [opNightHour] [int] NULL,
[opNightMin] [int] NULL, ) ON [PRIMARY] GO
考虑将其作为测试数据插入。列(用于测试目的)为startPayDateTime
和ToDateTime
INSERT INTO [myTestTable]
([JHID],[ToDateTime],[startPayDateTime],[opDayHour],[opDayMin],[opNightHour],[opNightMin])
VALUES (301533,'14-03-2016 01:54','14-03-2016 04:54',1,1,1,1),
(302488,'14-03-2016 01:54','14-03-2016 08:31',0,0,0,0),
(302676,'14-03-2016 01:54','28-03-2016 08:11',1,1,1,1) GO
所以现在我必须
UPDATE
SET opDayHour = (CASE WHEN ... THEN *value* ELSE 0 end),
opDayMin = (CASE WHEN ... THEN *value* ELSE 0 end),
opNightHour = (CASE WHEN ... THEN *value* ELSE 0 end),
opNightMin = (CASE WHEN ... THEN *value* ELSE 0 end),
如果我的问题不够明确,我如何感谢您的考虑留下评论! :)
答案 0 :(得分:2)
想法是检测第一天,一些洞日(如果存在)和最后一天(如果不是与第一天相同)。因此,我们只需要一天的计数表即可。缺点是那些第一个/最后一个间隔的更多计算。当你需要涉及许多中间变量的计算时,CROSS APPLY是一个方便的工具。 试试这个,您可能需要调整+ -1逻辑以符合您的规则。此查询计算分钟数,可以轻松转换为小时+分钟。
with myMinutes as (
select rn
-- day time is from 6:00 to 23:00
, mday = case when rn between 6*60 and 23*60-1 then 1 else 0 end
, mnight = 1 - case when rn between 6*60 and 23*60-1 then 1 else 0 end
from (select top(24*60) rn=row_number () over (order by (select null))
from sys.all_objects s1, sys.all_objects s2) t
)
select dayMinutes=r1.dayMin + case holedays when 0 then 0 else r2.dayMin + (holedays-1)*(23*60 - 6*60) end
, nightMinutes=r1.nightMin + case holedays when 0 then 0 else r2.nightMin + (holedays-1)*(24*60 -(23*60 - 6*60)) end
, totalMinutes= datediff(MINUTE, [FromDateTime], [ToDateTime]) -- control
,[JHID],[JetReg],[ArrFltID],[DepFltID],[ArrDateTime],[FromDateTime],[ToDateTime]
-- more columns sipped
from [myTestTable]
cross apply (select fD = dateadd(DAY,datediff(DAY,'19000101',[FromDateTime]),'19000101')
,tD = dateadd(DAY,datediff(DAY,'19000101',[ToDateTime]),'19000101')
,holedays = datediff(DAY,[FromDateTime],[ToDateTime]) ) xd
cross apply (select fFirstMin = datediff(MINUTE, fd, [FromDateTime])
,fLastMin = case holedays when 0 then datediff(MINUTE, td,[ToDateTime]) else 24*60 end - 1
,tFirstMin = 1
,tLastMin = datediff(MINUTE, td, [ToDateTime])
) xb
cross apply (select dayMin = sum(mm.mday)
, nightMin = sum(mm.mnight)
from myminutes mm
where mm.rn between fFirstMin and fLastMin ) r1
cross apply (select dayMin = sum(mm.mday)
, nightMin = sum(mm.mnight)
from myminutes mm
where mm.rn between tFirstMin and tLastMin ) r2
答案 1 :(得分:1)
您可以使用cte作为该计数:
DECLARE
@DateTime1 datetime = '2016-04-20 13:30',
@DateTime2 datetime = '2016-04-21 07:15'
;WITH times AS(
SELECT @DateTime1 as d,
CASE WHEN DATEPART(hour,@DateTime1) between 6 and 22 then 'd' else 'n' end as a,
0 as m
UNION ALL
SELECT DATEADD(minute,1,d),
CASE WHEN DATEPART(hour,DATEADD(minute,1,d)) between 6 and 22 then 'd' else 'n' end as a,
DATEDIFF(minute,d,DATEADD(minute,1,d))
FROM times
WHERE DATEADD(minute,1,d) <= @DateTime2
)
SELECT CASE WHEN a = 'd' THEN 'DayTime' ELSE 'NightTime' END as TimePart,
sum(m)/60 as H,
sum(m) - (sum(m)/60)* 60 as M
FROM times
GROUP BY a
OPTION (MAXRECURSION 0)
输出如下:
TimePart H M
--------- ----------- -----------
DayTime 10 45
NightTime 7 0
(2 row(s) affected)