2016-03-04 60 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