将日期时间拆分为一天中的1分钟插槽

时间:2017-11-10 08:27:52

标签: sql-server

我有一堆使用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

4 个答案:

答案 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