似乎有很多关于这个主题的信息,但是我没有足够的SQL知识来应用它来解决我的问题。
这是我目前正在使用的查询:
/* Number of successful logins per minute for a given date range */
SELECT
DATEADD(minute, DATEDIFF(minute, 0, AuditMessage.EventDateTime), 0) AS Time,
COUNT(AuditMessage.EventTypeCodeUid) AS CountSuccessfulLoginAttemptsPerMinute
FROM IRWSDB.dbo.AuditMessage
JOIN AuditEventTypeCode
ON AuditEventTypeCode.EventTypeCodeUid = AuditMessage.EventTypeCodeUid
WHERE AuditEventTypeCode.DisplayName = 'Login'
AND AuditMessage.EventDateTime >= CONVERT(DATETIME, '2016-03-03 00:00:00', 120)
AND AuditMessage.EventDateTime <= CONVERT(DATETIME, '2016-03-04 00:00:00', 120)
GROUP BY DATEADD(minute, DATEDIFF(minute, 0, AuditMessage.EventDateTime), 0)
ORDER BY DATEADD(minute, DATEDIFF(minute, 0, AuditMessage.EventDateTime), 0)
示例输出(按预期工作):
Time CountSuccessfulLoginAttemptsPerMinute
2016-03-03 17:48:00.000 1
2016-03-03 17:49:00.000 1
2016-03-03 17:50:00.000 1
2016-03-03 17:55:00.000 2
期望输出:
Time CountSuccessfulLoginAttemptsPerMinute
2016-03-03 17:48:00.000 1
2016-03-03 17:49:00.000 1
2016-03-03 17:50:00.000 1
2016-03-03 17:51:00.000 0
2016-03-03 17:52:00.000 0
2016-03-03 17:53:00.000 0
2016-03-03 17:54:00.000 0
2016-03-03 17:55:00.000 2
我试图修改上面的查询以获得所需的输出,但是我走下去的每一条路都是死路一条。任何帮助将不胜感激。谢谢。
答案 0 :(得分:1)
如果您的数据库没有一天中的每一分钟,它将无法获得所需的输出。除非你后端/任何会在每分钟将一条记录插入你的桌子或参考这个链接Fill empty dates in a matrix SSRS。然后你可以像这样修改你的查询
SELECT
DATEADD(minute, DATEDIFF(minute, 0, AuditMessage.EventDateTime), 0) AS Time,
ISNULL(COUNT(AuditMessage.EventTypeCodeUid),0) AS CountSuccessfulLoginAttemptsPerMinute
FROM IRWSDB.dbo.AuditMessage
JOIN AuditEventTypeCode
ON AuditEventTypeCode.EventTypeCodeUid = AuditMessage.EventTypeCodeUid
WHERE AuditEventTypeCode.DisplayName = 'Login'
AND AuditMessage.EventDateTime >= CONVERT(DATETIME, '2016-03-03 00:00:00', 120)
AND AuditMessage.EventDateTime <= CONVERT(DATETIME, '2016-03-04 00:00:00', 120)
GROUP BY DATEADD(minute, DATEDIFF(minute, 0, AuditMessage.EventDateTime), 0)
ORDER BY DATEADD(minute, DATEDIFF(minute, 0, AuditMessage.EventDateTime), 0)
答案 1 :(得分:0)
首先,您需要生成日期范围内的所有分钟。为此,您需要Tally Table。然后对原始查询执行LEFT JOIN
。
DECLARE @start DATETIME,
@end DATETIME
SELECT @start = '20160303', @end = '20160304'
;WITH E1(N) AS(
SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b),
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b),
CteTally(N) AS(
SELECT TOP(DATEDIFF(MINUTE, @start, @end) + 1) ROW_NUMBER() OVER(ORDER BY(SELECT NULL))
FROM E4
),
CteMinute(dt) AS(
SELECT dt = DATEADD(MINUTE, N-1, @start) FROM CteTally
)
SELECT
cm.dt AS [Time],
ISNULL(t.cnt, 0) AS CountSuccessfulLoginAttemptsPerMinute
FROM CteMinute cm
LEFT JOIN (
SELECT
DATEADD(MINUTE, DATEDIFF(MINUTE, 0, am.EventDateTime), 0) AS [Time],
COUNT(am.EventTypeUid) AS cnt
FROM IRWSDB.dbo.AuditMessage am
INNER JOIN AuditEventTypeCode atc
ON atc.EventTypeCodeUid = am.EventTypeCodeUid
WHERE
atc.DisplayName = 'Login'
AND am.EventDateTime >= @start
AND am.EventDateTime <= @end
GROUP BY DATEADD(MINUTE, DATEDIFF(MINUTE, 0, am.EventDateTime), 0)
) t
ON cm.dt = t.[Time]
GROUP BY cm.dt
答案 2 :(得分:0)
一种方法是使用LEFT JOIN&#34;每分钟列表&#34;到您当前的查询 第二种方法是UNION ALL使用&#34;每分钟列表的当前查询&#34;然后在Count
上执行SUM有很多方法可以创建每个分钟的列表&#34;比如使用tally / number表,递归cte,交叉连接等。
这是一个使用递归cte
的方法;with minutes as
(
select Time = convert(datetime, '2016-03-03')
union all
select Time = dateadd(minute, 1, Time)
from minutes
where Time < '2016-03-05'
)
select Time
from minues
方法1:LEFT JOIN
;with minutes as
(
select Time = convert(datetime, '2016-03-03')
union all
select Time = dateadd(minute, 1, Time)
from minutes
where Time < '2016-03-05'
),
data as
(
< your current query here without the order by clause>
)
select m.Time, isnull(CountSuccessfulLoginAttemptsPerMinute, 0) as CountSuccessfulLoginAttemptsPerMinute
from minues m
left join data d on m.Time = d.Time
方法2:UNION ALL
;with minutes as
(
select Time = convert(datetime, '2016-03-03')
union all
select Time = dateadd(minute, 1, Time)
from minutes
where Time < '2016-03-05'
)
select Time, sum(CountSuccessfulLoginAttemptsPerMinute) as CountSuccessfulLoginAttemptsPerMinute
FROM
(
< your current query here without the order by clause>
union all
select Time, 0 as CountSuccessfulLoginAttemptsPerMinute
from mintues
) d
group by Time