我有一组数据,我需要根据这些数据将每个事件(以及resourceid或所有者)的多个不同事件持续时间分成一个或多个30分钟的时间间隔。持续时间可能跨越一个半小时以上的间隔,我需要该事件恰好在该间隔中花费的时间。那就是我遇到麻烦的地方,找不到任何其他问题解决方案似乎可以按照我的要求解决。
我确实知道如何按时间间隔进行计数,但是不知道如何以一种不愚蠢的方式处理时间间隔。我没有经验,将不胜感激,朝正确的方向努力,因为我一直在考虑这个问题,并且摆弄了两天,现在没有任何表现。我最坏的情况是逐行游标源数据,进行数学运算,然后将结果插入表中,但是我认为那完全是精妙的,所以甚至都没有尝试过。
哦,性能不是问题...数据量很低。使用SS 2014。
(而且,很抱歉,我不明白你们是如何嵌入代码片段的,所以对于任何假冒或其他愚蠢的行为,我都表示歉意。)
这是源数据的样子(我将在下面放置一个create table / insert,以获取一个所有者或resourceid的一整天的数据,以进行测试)
ResourceID EventType EventStartDateTime EventEndDateTime Duration
16278 6 2018-07-11 10:53:58.163 2018-07-11 11:03:58.163 600
16278 3 2018-07-11 11:03:58.163 2018-07-11 11:16:29.970 751
16278 4 2018-07-11 11:16:29.970 2018-07-11 11:16:33.330 4
16278 5 2018-07-11 11:16:33.330 2018-07-11 11:24:06.977 453
16278 6 2018-07-11 11:24:06.977 2018-07-11 11:31:31.633 445
16278 7 2018-07-11 11:31:31.633 2018-07-11 11:31:31.633 0
16278 1 2018-07-11 12:30:44.020 2018-07-11 17:15:55.173 17111
16278 2 2018-07-11 12:30:44.023 2018-07-11 12:33:23.437 159
16278 3 2018-07-11 12:33:23.437 2018-07-11 12:38:55.467 332
etc.
这是我想要的结果,除了空白处填充:
declare @FirstDay smalldatetime = '20180711',
@LastDay smalldatetime = '20180711';
select top (24*2*datediff(day, @FirstDay, dateadd(day,1,@LastDay)))
dateadd(minute, 30*(row_number() over (order by (select NULL))-1),
@FirstDay) as IntervalStartTime
, 0 as resourceid, '' as eventtype, 0 as SecWithinInterval
into ##Interval
from master.dbo.spt_values;
这是创建表/插入:
create table source_data (resourceid int, eventtype int, eventstartdatetime
datetime
, eventenddatetime datetime, duration int)
insert into source_data values
(16278,6,2018-07-11 10:53:58.163,2018-07-11 11:03:58.163,600),
(16278,3,2018-07-11 11:03:58.163,2018-07-11 11:16:29.970,751),
(16278,4,2018-07-11 11:16:29.970,2018-07-11 11:16:33.330,4),
(16278,5,2018-07-11 11:16:33.330,2018-07-11 11:24:06.977,453),
(16278,6,2018-07-11 11:24:06.977,2018-07-11 11:31:31.633,445),
(16278,7,2018-07-11 11:31:31.633,2018-07-11 11:31:31.633,0),
(16278,1,2018-07-11 12:30:44.020,2018-07-11 17:15:55.173,17111),
(16278,2,2018-07-11 12:30:44.023,2018-07-11 12:33:23.437,159),
(16278,3,2018-07-11 12:33:23.437,2018-07-11 12:38:55.467,332),
(16278,4,2018-07-11 12:38:55.467,2018-07-11 12:38:58.677,3),
(16278,5,2018-07-11 12:38:58.677,2018-07-11 12:45:09.793,371),
(16278,6,2018-07-11 12:45:09.793,2018-07-11 12:47:20.173,131),
(16278,3,2018-07-11 12:47:20.173,2018-07-11 12:54:51.057,451),
(16278,4,2018-07-11 12:54:51.057,2018-07-11 12:54:53.383,2),
(16278,5,2018-07-11 12:54:53.383,2018-07-11 12:59:27.373,274),
(16278,6,2018-07-11 12:59:27.373,2018-07-11 13:02:25.813,178),
(16278,3,2018-07-11 13:02:25.813,2018-07-11 13:02:49.173,24),
(16278,4,2018-07-11 13:02:49.173,2018-07-11 13:02:51.490,2),
(16278,5,2018-07-11 13:02:51.490,2018-07-11 13:05:30.453,159),
(16278,3,2018-07-11 13:05:30.453,2018-07-11 13:05:30.453,0),
(16278,4,2018-07-11 13:05:30.453,2018-07-11 13:05:33.183,3),
(16278,5,2018-07-11 13:05:33.183,2018-07-11 13:15:55.777,622),
(16278,6,2018-07-11 13:15:55.777,2018-07-11 13:16:18.970,23),
(16278,2,2018-07-11 13:16:18.970,2018-07-11 13:23:32.787,434),
(16278,3,2018-07-11 13:23:32.787,2018-07-11 13:28:12.907,280),
(16278,4,2018-07-11 13:28:12.907,2018-07-11 13:28:16.073,4),
(16278,5,2018-07-11 13:28:16.073,2018-07-11 13:32:47.177,271),
(16278,6,2018-07-11 13:32:47.177,2018-07-11 13:37:45.500,298),
(16278,3,2018-07-11 13:37:45.500,2018-07-11 13:43:59.183,374),
(16278,4,2018-07-11 13:43:59.183,2018-07-11 13:44:01.507,2),
(16278,5,2018-07-11 13:44:01.507,2018-07-11 13:50:04.983,363),
(16278,6,2018-07-11 13:50:04.983,2018-07-11 13:50:43.860,39),
(16278,3,2018-07-11 13:50:43.860,2018-07-11 13:57:21.817,398),
(16278,4,2018-07-11 13:57:21.817,2018-07-11 13:57:24.177,3),
(16278,5,2018-07-11 13:57:24.177,2018-07-11 14:07:57.677,633),
(16278,6,2018-07-11 14:07:57.677,2018-07-11 14:14:08.553,371),
(16278,3,2018-07-11 14:14:08.553,2018-07-11 14:28:57.117,889),
(16278,4,2018-07-11 14:28:57.117,2018-07-11 14:28:59.440,2),
(16278,5,2018-07-11 14:28:59.440,2018-07-11 14:31:50.793,171),
(16278,6,2018-07-11 14:31:50.793,2018-07-11 14:33:08.727,78),
(16278,3,2018-07-11 14:33:08.727,2018-07-11 14:38:30.820,322),
(16278,2,2018-07-11 14:38:30.820,2018-07-11 14:44:22.197,352),
(16278,2,2018-07-11 14:44:22.197,2018-07-11 15:01:45.453,1043),
(16278,3,2018-07-11 15:01:45.453,2018-07-11 15:13:38.823,713),
(16278,4,2018-07-11 15:13:38.823,2018-07-11 15:13:42.247,4),
(16278,5,2018-07-11 15:13:42.247,2018-07-11 15:18:57.147,315),
(16278,6,2018-07-11 15:18:57.147,2018-07-11 15:19:12.297,15),
(16278,3,2018-07-11 15:19:12.297,2018-07-11 15:29:43.060,631),
(16278,4,2018-07-11 15:29:43.060,2018-07-11 15:29:46.160,3),
(16278,5,2018-07-11 15:29:46.160,2018-07-11 15:30:37.130,51),
(16278,6,2018-07-11 15:30:37.130,2018-07-11 15:30:44.783,7),
(16278,3,2018-07-11 15:30:44.783,2018-07-11 15:37:46.373,422),
(16278,4,2018-07-11 15:37:46.373,2018-07-11 15:37:49.080,3),
(16278,5,2018-07-11 15:37:49.080,2018-07-11 15:43:52.273,363),
(16278,6,2018-07-11 15:43:52.273,2018-07-11 15:48:54.730,302),
(16278,3,2018-07-11 15:48:54.730,2018-07-11 15:56:47.407,473),
(16278,4,2018-07-11 15:56:47.407,2018-07-11 15:56:49.820,2),
(16278,5,2018-07-11 15:56:49.820,2018-07-11 16:01:40.780,291),
(16278,6,2018-07-11 16:01:40.780,2018-07-11 16:04:02.403,142),
(16278,3,2018-07-11 16:04:02.403,2018-07-11 16:20:53.963,1011),
(16278,4,2018-07-11 16:20:53.963,2018-07-11 16:21:00.817,7),
(16278,3,2018-07-11 16:21:00.817,2018-07-11 16:35:54.190,894),
(16278,4,2018-07-11 16:35:54.190,2018-07-11 16:35:56.473,2),
(16278,5,2018-07-11 16:35:56.473,2018-07-11 16:38:37.587,161),
(16278,6,2018-07-11 16:38:37.587,2018-07-11 16:45:29.563,412),
(16278,3,2018-07-11 16:45:29.563,2018-07-11 16:57:20.893,711),
(16278,4,2018-07-11 16:57:20.893,2018-07-11 16:57:24.000,4),
(16278,5,2018-07-11 16:57:24.000,2018-07-11 17:10:22.210,778),
(16278,6,2018-07-11 17:10:22.210,2018-07-11 17:15:55.173,333),
(16278,7,2018-07-11 17:15:55.173,2018-07-11 17:15:55.173,0)
非常感谢大家,为您提供的任何帮助!
答案 0 :(得分:0)
此示例使用数字表来得出时间间隔。这是一段快速而又肮脏的代码,并且不假定您已有数字表。出于本示例的目的,示例数据已加载到名为## source_data的全局临时表中。
SET NOCOUNT ON
-- Create a temporary numbers table to demonstrate its use.
-- We only need numbers up to 47, but will be creating numbers up to 336 to cover
-- periods of up to a week. This table will also include zero.
Declare @DailyIntervals int = 48,
@maxDays int = 7
-- This calculates the number of recursive inserts needed to reach your maximum value
-- NOTE: This is based off of manually inserting your first four values into the table first!
DECLARE @loop int
SET @loop = CEILING(LOG(@DailyIntervals * @maxDays, 2))-2
--SELECT @loop
Declare @m int
CREATE TABLE ##Nums (i int primary key clustered);
INSERT INTO ##Nums VALUES (1), (2), (3), (4); -- Seed the table
SET @m = 4
WHILE @loop > 0
BEGIN
INSERT INTO ##nums SELECT I + @m FROM ##Nums
SET @m = @@ROWCOUNT * 2 -- max value in table now
SET @loop = @loop - 1
END
INSERT INTO ##nums Values (0) -- add the zero value
--SELECT MAX(I) FROM ##Nums
-- Look at July 11th only for now.
DECLARE @BeginDt datetime = '2018-07-11',
@EndDt datetime = '2018-07-11';
-- Build a working table of half hour intervals
WITH hhrs as (
SELECT Dateadd(MINUTE, 30 * i, @BeginDt) as StartTm,
Dateadd(MINUTE, 30 * (i+1), @BeginDt) as EndTm
FROM ##Nums
WHERE i BETWEEN 0 and (DateDiff(Day, @BeginDt, @EndDt) * 48 + 47)
),
-- Get all of the data except duration
Src as (
SELECT
sd.resourceid,
sd.eventtype,
CASE
WHEN sd.eventstartdatetime <= StartTm
THEN StartTm
Else sd.eventstartdatetime
End as EventStart,
CASE
WHEN sd.eventEnddatetime > EndTm
THEN EndTm
Else sd.eventenddatetime
End as EventEnd
FROM hhrs h
INNER JOIN ##source_data sd
ON sd.eventstartdatetime < EndTm
AND sd.eventenddatetime >= StartTm
)
-- Final output including duration
SELECT
ResourceID,
EventType,
EventStart,
EventEnd,
DateDiff(SECOND, EventStart, EventEnd) as Duration
FROM Src
ORDER BY EventStart, EventEnd
DROP TABLE ##Nums
这是我从样本数据中收到的输出:
ResourceID EventType EventStart EventEnd Duration
16278 6 2018-07-11 10:53:58.163 2018-07-11 11:00:00.000 362
16278 6 2018-07-11 11:00:00.000 2018-07-11 11:03:58.163 238
16278 3 2018-07-11 11:03:58.163 2018-07-11 11:16:29.970 751
16278 4 2018-07-11 11:16:29.970 2018-07-11 11:16:33.330 4
16278 5 2018-07-11 11:16:33.330 2018-07-11 11:24:06.977 453
16278 6 2018-07-11 11:24:06.977 2018-07-11 11:30:00.000 354
16278 6 2018-07-11 11:30:00.000 2018-07-11 11:31:31.633 91
16278 7 2018-07-11 11:31:31.633 2018-07-11 11:31:31.633 0
16278 1 2018-07-11 12:30:44.020 2018-07-11 13:00:00.000 1756
16278 2 2018-07-11 12:30:44.023 2018-07-11 12:33:23.437 159
16278 3 2018-07-11 12:33:23.437 2018-07-11 12:38:55.467 332
16278 4 2018-07-11 12:38:55.467 2018-07-11 12:38:58.677 3
16278 5 2018-07-11 12:38:58.677 2018-07-11 12:45:09.793 371
16278 6 2018-07-11 12:45:09.793 2018-07-11 12:47:20.173 131
16278 3 2018-07-11 12:47:20.173 2018-07-11 12:54:51.057 451
16278 4 2018-07-11 12:54:51.057 2018-07-11 12:54:53.383 2
16278 5 2018-07-11 12:54:53.383 2018-07-11 12:59:27.373 274
16278 6 2018-07-11 12:59:27.373 2018-07-11 13:00:00.000 33
16278 6 2018-07-11 13:00:00.000 2018-07-11 13:02:25.813 145
16278 1 2018-07-11 13:00:00.000 2018-07-11 13:30:00.000 1800
16278 3 2018-07-11 13:02:25.813 2018-07-11 13:02:49.173 24
16278 4 2018-07-11 13:02:49.173 2018-07-11 13:02:51.490 2
16278 5 2018-07-11 13:02:51.490 2018-07-11 13:05:30.453 159
16278 3 2018-07-11 13:05:30.453 2018-07-11 13:05:30.453 0
16278 4 2018-07-11 13:05:30.453 2018-07-11 13:05:33.183 3
16278 5 2018-07-11 13:05:33.183 2018-07-11 13:15:55.777 622
16278 6 2018-07-11 13:15:55.777 2018-07-11 13:16:18.970 23
16278 2 2018-07-11 13:16:18.970 2018-07-11 13:23:32.787 434
16278 3 2018-07-11 13:23:32.787 2018-07-11 13:28:12.907 280
16278 4 2018-07-11 13:28:12.907 2018-07-11 13:28:16.073 4
16278 5 2018-07-11 13:28:16.073 2018-07-11 13:30:00.000 104
16278 5 2018-07-11 13:30:00.000 2018-07-11 13:32:47.177 167
16278 1 2018-07-11 13:30:00.000 2018-07-11 14:00:00.000 1800
16278 6 2018-07-11 13:32:47.177 2018-07-11 13:37:45.500 298
16278 3 2018-07-11 13:37:45.500 2018-07-11 13:43:59.183 374
16278 4 2018-07-11 13:43:59.183 2018-07-11 13:44:01.507 2
16278 5 2018-07-11 13:44:01.507 2018-07-11 13:50:04.983 363
16278 6 2018-07-11 13:50:04.983 2018-07-11 13:50:43.860 39
16278 3 2018-07-11 13:50:43.860 2018-07-11 13:57:21.817 398
16278 4 2018-07-11 13:57:21.817 2018-07-11 13:57:24.177 3
16278 5 2018-07-11 13:57:24.177 2018-07-11 14:00:00.000 156
16278 5 2018-07-11 14:00:00.000 2018-07-11 14:07:57.677 477
16278 1 2018-07-11 14:00:00.000 2018-07-11 14:30:00.000 1800
16278 6 2018-07-11 14:07:57.677 2018-07-11 14:14:08.553 371
16278 3 2018-07-11 14:14:08.553 2018-07-11 14:28:57.117 889
16278 4 2018-07-11 14:28:57.117 2018-07-11 14:28:59.440 2
16278 5 2018-07-11 14:28:59.440 2018-07-11 14:30:00.000 61
16278 5 2018-07-11 14:30:00.000 2018-07-11 14:31:50.793 110
16278 1 2018-07-11 14:30:00.000 2018-07-11 15:00:00.000 1800
16278 6 2018-07-11 14:31:50.793 2018-07-11 14:33:08.727 78
16278 3 2018-07-11 14:33:08.727 2018-07-11 14:38:30.820 322
16278 2 2018-07-11 14:38:30.820 2018-07-11 14:44:22.197 352
16278 2 2018-07-11 14:44:22.197 2018-07-11 15:00:00.000 938
16278 2 2018-07-11 15:00:00.000 2018-07-11 15:01:45.453 105
16278 1 2018-07-11 15:00:00.000 2018-07-11 15:30:00.000 1800
16278 3 2018-07-11 15:01:45.453 2018-07-11 15:13:38.823 713
16278 4 2018-07-11 15:13:38.823 2018-07-11 15:13:42.247 4
16278 5 2018-07-11 15:13:42.247 2018-07-11 15:18:57.147 315
16278 6 2018-07-11 15:18:57.147 2018-07-11 15:19:12.297 15
16278 3 2018-07-11 15:19:12.297 2018-07-11 15:29:43.060 631
16278 4 2018-07-11 15:29:43.060 2018-07-11 15:29:46.160 3
16278 5 2018-07-11 15:29:46.160 2018-07-11 15:30:00.000 14
16278 5 2018-07-11 15:30:00.000 2018-07-11 15:30:37.130 37
16278 1 2018-07-11 15:30:00.000 2018-07-11 16:00:00.000 1800
16278 6 2018-07-11 15:30:37.130 2018-07-11 15:30:44.783 7
16278 3 2018-07-11 15:30:44.783 2018-07-11 15:37:46.373 422
16278 4 2018-07-11 15:37:46.373 2018-07-11 15:37:49.080 3
16278 5 2018-07-11 15:37:49.080 2018-07-11 15:43:52.273 363
16278 6 2018-07-11 15:43:52.273 2018-07-11 15:48:54.730 302
16278 3 2018-07-11 15:48:54.730 2018-07-11 15:56:47.407 473
16278 4 2018-07-11 15:56:47.407 2018-07-11 15:56:49.820 2
16278 5 2018-07-11 15:56:49.820 2018-07-11 16:00:00.000 191
16278 5 2018-07-11 16:00:00.000 2018-07-11 16:01:40.780 100
16278 1 2018-07-11 16:00:00.000 2018-07-11 16:30:00.000 1800
16278 6 2018-07-11 16:01:40.780 2018-07-11 16:04:02.403 142
16278 3 2018-07-11 16:04:02.403 2018-07-11 16:20:53.963 1011
16278 4 2018-07-11 16:20:53.963 2018-07-11 16:21:00.817 7
16278 3 2018-07-11 16:21:00.817 2018-07-11 16:30:00.000 540
16278 3 2018-07-11 16:30:00.000 2018-07-11 16:35:54.190 354
16278 1 2018-07-11 16:30:00.000 2018-07-11 17:00:00.000 1800
16278 4 2018-07-11 16:35:54.190 2018-07-11 16:35:56.473 2
16278 5 2018-07-11 16:35:56.473 2018-07-11 16:38:37.587 161
16278 6 2018-07-11 16:38:37.587 2018-07-11 16:45:29.563 412
16278 3 2018-07-11 16:45:29.563 2018-07-11 16:57:20.893 711
16278 4 2018-07-11 16:57:20.893 2018-07-11 16:57:24.000 4
16278 5 2018-07-11 16:57:24.000 2018-07-11 17:00:00.000 156
16278 5 2018-07-11 17:00:00.000 2018-07-11 17:10:22.210 622
16278 1 2018-07-11 17:00:00.000 2018-07-11 17:15:55.173 955
16278 6 2018-07-11 17:10:22.210 2018-07-11 17:15:55.173 333
16278 7 2018-07-11 17:15:55.173 2018-07-11 17:15:55.173 0
答案 1 :(得分:0)
您可以使用一点“递归”(与CTE一起)来建立时间表,并将其与source_data结合起来以找到所有区间的交集。 在我的解决方案中,我没有使用您的“持续时间”字段,因为无论如何我必须计算间隔的长度(以秒为单位)。 CTE EventDays全天“创建”(如果查询超过100天,则必须更改MAXRECURSION选项或以较大的间隔(例如,甚至几个月或几年)以CTE开始),而CTE HalfHours会创建所有haf-hour-建立时间表的每一天的时间间隔:
DECLARE @FirstDay smalldatetime = '20180711',
@LastDay smalldatetime = '20180711';
WITH
EventDays (EventDay, NextDay, MaxDay) AS (
SELECT @FirstDay, DATEADD(day, 1, @FirstDay), @LastDay
UNION ALL
SELECT NextDay, DATEADD(day, 1, NextDay), MaxDay
FROM EventDays WHERE NextDay <= MaxDay
),
HalfHours (StartTime, EndTime, MaxTime) AS (
SELECT EventDay, DATEADD(minute, 30, EventDay), NextDay
FROM EventDays
UNION ALL
SELECT EndTime, DATEADD(minute, 30, EndTime), MaxTime
FROM HalfHours WHERE EndTime < MaxTime
)
SELECT ResourceID, EventType, isec.StartTime, isec.EndTime,
DATEDIFF(second, isec.StartTime, isec.EndTime) AS Duration
FROM source_data sd
INNER JOIN HalfHours hh
ON sd.EventEndDatetime > hh.StartTime AND sd.EventStartDatetime < hh.EndTime
CROSS APPLY (VALUES ( -- intersection StartTime and EndTime
CASE
WHEN sd.EventStartDatetime > hh.StartTime THEN sd.EventStartDatetime
ELSE hh.StartTime
END,
CASE
WHEN sd.EventEndDatetime < hh.EndTime THEN sd.EventEndDatetime
ELSE hh.EndTime
END)
) isec (StartTime, EndTime)
ORDER BY isec.StartTime;