我有一个带有日期时间列的表,为简单,类似的目的将其视为事件日志。
我想制作一份报告,详细说明每天发生的平均事件数,精确到30分钟。
所以逻辑是,
我也不希望在我的数据中有任何时间漏洞,例如,如果在00:00 - 00:30范围内没有发生任何事情,我想报告0,而不是丢失一行。< / p>
我怎样才能做到这一点?
答案 0 :(得分:1)
WITH TestDates (date) AS (
SELECT CONVERT(DATETIME, '2011-11-15 10:00') UNION ALL
SELECT CONVERT(DATETIME, '2011-11-15 11:31') UNION ALL
SELECT CONVERT(DATETIME, '2011-11-16 10:00')
-- CTE to generate 4 million rows with a sequential integer starting at 0
), GeneratedRows (seq) AS (
SELECT ROW_NUMBER() OVER (ORDER BY N1.number) - 1
FROM master..spt_values AS N1
CROSS JOIN master..spt_values AS N2
WHERE N1.name IS NULL
AND N2.name IS NULL
), RoundedTestDates (date) AS (
SELECT CASE
-- Subtract the minute part
WHEN DATEPART(MINUTE, date) < 25 THEN DATEADD(MINUTE, -1 * DATEPART(MINUTE, date), date)
-- Subtract the minute part, then add an hour
WHEN DATEPART(MINUTE, date) >= 45 THEN DATEADD(HOUR, 1, DATEADD(MINUTE, -1 * DATEPART(MINUTE, date), date))
-- Subtract the minute part, then add an half-hour
ELSE DATEADD(MINUTE, 30, DATEADD(MINUTE, -1 * DATEPART(MINUTE, date), date))
END
FROM TestDates
)
SELECT rounded_date = GeneratedPeriod.date
, ocurrences = COUNT(RoundedTestDates.date)
FROM (SELECT DATEADD(MINUTE, 30 * seq, (SELECT MIN(date) FROM RoundedTestDates))
FROM GeneratedRows
) AS GeneratedPeriod (date)
LEFT JOIN RoundedTestDates
ON GeneratedPeriod.date = RoundedTestDates.date
WHERE GeneratedPeriod.date <= (SELECT MAX(date) FROM RoundedTestDates)
GROUP BY GeneratedPeriod.date
ORDER BY 1
答案 1 :(得分:1)
以下是您需要的代码:(在sql2008中测试,运行正常!)
-- Table with the 48 30mins periods of the day
CREATE TABLE #Periods
(
Num INT
)
DECLARE @idt INT
SET @idt = 1
WHILE (@idt <= 48)
BEGIN
INSERT INTO #Periods VALUES (@idt)
SET @idt = @idt + 1
END
--Average of the count for each period on all days.
SELECT DayTable.Num, AVG(CAST(DayTable.DayCount AS DECIMAL))
FROM
( --Total incidents for each interval on each day.
SELECT CAST(FLOOR(CAST(#MyLog.LogDate AS FLOAT)) AS DATETIME) AS DayWithOutTime,
#Periods.Num AS Num,
COUNT(#MyLog.ID) AS DayCount
FROM #Periods LEFT JOIN #MyLog
ON #Periods.Num = (DATEPART(hh, #MyLog.LogDate)*60 + DATEPART(mi,#MyLog.LogDate))/30
GROUP BY CAST(FLOOR(CAST(#MyLog.LogDate AS FLOAT)) AS DATETIME),
#Periods.Num
) AS DayTable
GROUP BY DayTable.Num
DROP TABLE #Periods
其中#NyLog是您的日期时间所在的表。它显示了每30分钟的发生率计数。期间1是00:00 - &gt; 00:30和48期是23:30 - &gt; 24:00。
答案 2 :(得分:0)
在sybase sql中是这样的,在sql-server中你可能需要做一些改变但不多:)
create procedure Test @startDay varchar(8), @endDay varchar(8)
as
declare @ocurrence int
declare @numberOfDays int
select @numberOfDays = 0
create table #intervals (
interval_hour int,
interval_min_minute int,
interval_max_minute int,
ocurrences int
)
create table #insertions (
hour int,
minute int
)
declare @hour int, @minute int
select @hour = 0
-- create the intervals
while (@hour <> 24)
begin
insert into #intervals values(@hour,0,29,0)
insert into #intervals values(@hour,30,59,0)
select @hour = @hour + 1
end
while(@startDay <> @endDay)
begin
insert into #insertions
select datepart(hh, *yourcolumn*), datepart(mm, *yourcolumn*) from *yourdb..yourtable* where convert(varchar(8), *yourcolumn*, 112) = @startDay
select @startDay = convert(varchar(8), dateadd(dd, 1, convert(datetime, @startDay, 112)), 112)
select @numberOfDays = @numberOfDays + 1
end
declare cursor1 cursor for
select hour, minute from #insertions
open cursor1
fetch cursor1 into @hour, @minute
while (@@sqlstatus=0)
begin
update #intervals
set i.ocurrences = i.ocurrences + 1
from #intervals i
where interval_hour = @hour and @minute between interval_min_minute and interval_max_minute
fetch cursor1 into @hour, @minute
end
close cursor1
select interval_hour 'hour', interval_min_minute 'min minute', interval_max_minute 'max minute', ocurrences,
case when ocurrences > 0 then convert(float, ocurrences) / convert(float, @numberOfDays) else 0 end 'ocurrences average' from #intervals
drop table #intervals
drop table #insertions
go
答案 3 :(得分:0)
我所做的是使用一个辅助数字表(1列表,数字为1到1百万)并加入它,将数字的值与dateadd函数一起添加到日期的午夜。 / p>
因为你想要30分钟的间隔,那么你想要使用dateadd(分钟,数字* 30,你的日期),其中数字&lt; = 48(因为一天有1440分钟)/ 30 = 48间隔。这将创建您的时间间隔。
然后只计算在时间间隔之间发生的事件。