我有一堆使用slqserver express 2012的DateTimes,我想将这些日期时间拆分并分配到一天中的1分钟时段,并指出数据中可能会有超过一天的时间。但是,我将首先专注于只有一天的数据。例如,如果我有以下输入数据:
OnTime OffTime Duration
2017-11-01 00:03 2017-11-01 00:04 1
2017-11-01 00:08 2017-11-01 00:11 3
2017-11-01 00:13 2017-11-01 00:14 1
2017-11-01 00:21 2017-11-01 00:24 3
2017-11-01 00:26 2017-11-01 00:30 4
我希望将输出插入当天的每个分钟位置,当天有1440分钟,如果日期时间跨越有问题的分钟位置,则逻辑1将放入相应的列中并且为0否则,从0000开始=分钟0和2359 =分钟1439.输出数据将类似于:
Minute Active
0 0
1 0
2 0
3 1
4 0
5 0
6 0
7 0
8 1
9 1
10 1
11 0
12 0
13 1
14 0
15 0
... ...
1440 0
我原本以为我可以在一分钟的时间内交叉使用日期时间,但我不确切知道该去哪里,或者它是否是最佳方式。我也有兴趣将这个想法延伸到几秒或几小时的间隙而不是几分钟等。任何帮助都非常感激。
问候,M
答案 0 :(得分:0)
尝试以下代码
CREATE FUNCTION [dbo].[GetAllMinutesBetweenRange]
(
@FromDate DATETIME
,@ToDate DATETIME
)
RETURNS @Dates TABLE
(
DateVal DATETIME
)
AS
BEGIN
;WITH CTE
AS
(
SELECT @FromDate AS FromDate
UNION ALL
SELECT DATEADD(MI,1,FromDate)
FROM CTE
WHERE FromDate < @ToDate
)
INSERT INTO @Dates
SELECT FromDate FROM CTE
option (maxrecursion 0)
RETURN;
END
SELECT ROW_NUMBER() OVER(ORDER BY DATEVAL) AS MINUTE
,DATEVAL
,CASE WHEN TableA.OnTime IS NULL THEN 0 ELSE 1 END
FROM [dbo].[GetAllMinutesBetweenRange]('2017-11-01 00:00:00','2017-11-01 23:59:00') Res1
LEFT JOIN TableA ON Res1.DateVal >= TableA.OnTime AND Res1.DateVal< TableA.OffTime
可以修改表值函数以处理秒数
希望这有帮助!
答案 1 :(得分:0)
试试这个
WITH CTE
AS
(
SELECT
SeqNo = 0,
Strt = CAST(CAST(GETDATE() AS DATE) AS DATETIME)
UNION ALL
SELECT
SeqNo = SeqNo+1,
Strt = DATEADD(minute,1,Strt)
FROM CTE
WHERE CAST(CAST(Strt AS DATE) AS DATETIME)=CAST(CAST(GETDATE() AS DATE) AS DATETIME)
)
SELECT
SeqNo AS Minute,
Active = CASE WHEN T1.Duration IS NOT NULL THEN 1 ELSE 0 END
FROM CTE C1
LEFT JOIN T1
ON CAST(T1.OnTime AS DATETIME) >= CAST(C1.Strt AS DATETIME)
AND CAST(T1.OffTime AS DATETIME) <= CAST(C1.Strt AS DATETIME)
OPTION (maxrecursion 0)
答案 2 :(得分:0)
此查询将生成某个日期所需的结果集。你可以把它放在一个函数中。 cte
部分仅用于演示目的,您必须使用表格。
DECLARE @somedate date = '2017-11-01'
DECLARE @somedateN nvarchar(10) = CAST(@somedate as nvarchar(10))
DECLARE @start datetime = CAST(@somedateN +' 00:00:00' as datetime),
@end datetime = CAST(@somedateN +' 23:59:59' as datetime)
-- Simulation of your table with some new rows
;WITH cte AS (
SELECT OnTime,
OffTime,
Duration
FROM (VALUES
('2017-11-01 00:03', '2017-11-01 00:04', 1),
('2017-11-01 00:08', '2017-11-01 00:11', 3),
('2017-11-01 00:13', '2017-11-01 00:14', 1),
('2017-11-01 00:21', '2017-11-01 00:24', 3),
('2017-11-01 00:26', '2017-11-01 00:30', 4),
('2017-11-01 00:59', '2017-11-01 01:30', 31), -- new row
('2017-11-01 23:57', '2017-11-02 00:02', 5) -- new row
) as t(OnTime,OffTime,Duration)
), minutes_ AS ( -- table with all minutes from 0 to 1440
SELECT 0 as [Minute]
UNION ALL
SELECT [Minute] + 1
FROM minutes_
WHERE [Minute] <= DATEDIFF(minute,@start,@end)
)
-- here we go!
SELECT [Minute],
CASE WHEN c.Duration IS NULL THEN 0 ELSE 1 END as [Active]
FROM minutes_ m
LEFT JOIN cte c
ON m.[Minute] >= DATEDIFF(minute,@start,OnTime)
AND m.[Minute] < DATEDIFF(minute,@start,OffTime)
OPTION (MAXRECURSION 0)
输出:
Minute Active
----------- -----------
0 0
1 0
2 0
3 1
4 0
5 0
6 0
7 0
8 1
9 1
10 1
11 0
12 0
13 1
...
1434 0
1435 0
1436 0
1437 1
1438 1
1439 1
1440 1
答案 3 :(得分:0)
另一种解决方案供您考虑。此查询主要关注一天:
declare @dateTable table(OnTime datetime, OffTime datetime, Duration int)
insert into @dateTable values('2017-11-01 00:03','2017-11-01 00:04',1)
insert into @dateTable values('2017-11-01 00:08','2017-11-01 00:11',3)
insert into @dateTable values('2017-11-01 00:13','2017-11-01 00:14',1)
insert into @dateTable values('2017-11-01 00:21','2017-11-01 00:24',3)
insert into @dateTable values('2017-11-01 00:26','2017-11-01 00:30',4)
declare @result table(minute int, active bit)
declare @length int = 1440
declare @index int = 0
while @index <= @length
begin
insert into @result values(@index,0)
set @index = @index + 1
end
update t
set t.active = case when d.OnTime is not null then 1 else 0 end
from @result as t
left join @dateTable as d on t.minute >= datepart(hour,ontime)*60 + datepart(minute,ontime)
and t.minute < datepart(hour,offtime)*60 + datepart(minute,offtime)
select * from @result