2016-03-04 61 views
0

看起来有很多关于此主题的信息,但我没有足够的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

你需要手动创建所需的值,然后修改您的查询,让你离开加盟值。 – ZLK

+1

您需要列出您希望显示在结果集中的所有分钟数,然后LEFT将其加入COUNT。 –

回答

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) 
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 
0

一种方法是使用“每分钟的名单” LEFT JOIN到当前的查询 第二个办法是UNION与“每分钟的名单”目前所有的查询,然后做一个SUM上计数

有5方法来创建交叉连接等,使用理货/数字表,递归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