簡體   English   中英

SQL Server:每天的平均警報數,不包括沒有警報的天數

[英]SQL Server : average count of alerts per day, not including days with no alerts

我有一個表充當消息日志,其中兩個鍵表是TIMESTAMPTEXT 我正在研究一個查詢,該查詢可捕獲過去30天(基於TIMESTAMP )的所有警報(來自TEXT ),並提供這些警報的每日平均值。

到目前為止,這是查詢:

--goback 30 days start at midnight
declare @olderdate as datetime
set @olderdate = DATEADD(Day, -30, DATEDIFF(Day, 0, GetDate()))

--today at 11:59pm
declare @today as datetime
set @today = dateadd(ms, -3, (dateadd(day, +1, convert(varchar, GETDATE(), 101))))
print @today

--Grab average alerts per day over 30 days
select 
    avg(x.Alerts * 1.0 / 30)
from
    (select count(*) as Alerts 
     from MESSAGE_LOG 
     where text like 'The process%' 
       and text like '%has alerted%'
       and TIMESTAMP between @olderdate and @today) X

但是,我想添加一些內容來檢查一天是否有任何警報,並且如果當天沒有警報,則不將其包括在平均值中。 例如,如果一個月有90個警報,但它們全天都在發生,那么我不希望平均值為每天3個警報,因為這顯然具有誤導性。

有沒有辦法將其合並到查詢中? 我已經搜索了其他解決方案,但是還沒有任何解決方案。

這不是為您的查詢而寫的,因為我沒有任何DDL或示例數據,因此,我將提供一個非常簡單的示例,而不是您將如何執行此操作。

USE Sandbox;
GO

CREATE TABLE dbo.AlertMessage (ID int IDENTITY(1,1),
                               AlertDate date);

INSERT INTO dbo.AlertMessage (AlertDate)
VALUES('20190101'),('20190101'),('20190105'),('20190110'),('20190115'),('20190115'),('20190115');
GO

--Use a CTE to count per day:
WITH Tots AS (
    SELECT AlertDate,
           COUNT(ID) AS Alerts
    FROM dbo.AlertMessage
    GROUP BY AlertDate)
--Now the average
SELECT AVG(Alerts*1.0) AS DayAverage
FROM Tots;
GO

--Clean up
DROP TABLE dbo.AlertMessage;

除了將結果除以30所得的平均值以外,還可以除以不同天數的計數。

select 
    avg(x.Alerts * 1.0 / x.dd)
from
    (select count(*) as Alerts, count(distinct CAST([TIMESTAMP] AS date)) AS dd
...

您正在嘗試計算雙重總計:每日總計的平均值。

不使用CTE的情況下 ,您也可以嘗試使用此方法,這種方法通常可以工作數月。

--get a list of events per day
DECLARE @Event TABLE
(
    ID INT NOT NULL IDENTITY(1, 1)
    ,DateLocalTz DATE NOT NULL--make sure to handle time zones
    ,YearLocalTz AS DATEPART(YEAR, DateLocalTz) PERSISTED
    ,MonthLocalTz AS DATEPART(MONTH, DateLocalTz) PERSISTED
)
/*
INSERT INTO @Event(EntryDateLocalTz)
SELECT DISTINCT CONVERT(DATE, TIMESTAMP)--presumed to be in your local time zone because you did not specify
FROM dbo.MESSAGE_LOG
WHERE UPPER([TEXT]) LIKE 'THE PROCESS%' AND UPPER([TEXT]) LIKE '%HAS ALERTED%'--case insenitive
*/
INSERT INTO @Event(DateLocalTz)
VALUES ('2018-12-31'), ('2019-01-01'), ('2019-01-01'), ('2019-01-01'), ('2019-01-12'), ('2019-01-13')
--get average number of alerts per alerting day each month
--  (this will not return months with no alerts,
--  use a LEFT OUTER JOIN against a month list table if you need to include uneventful months)
SELECT
    YearLocalTz
    ,MonthLocalTz
    ,AvgAlertsOfAlertingDays = AVG(CONVERT(REAL, NumDailyAlerts))
FROM
    (
        SELECT
            YearLocalTz
            ,MonthLocalTz
            ,DateLocalTz
            ,NumDailyAlerts = COUNT(*)
        FROM @Event
        GROUP BY YearLocalTz, MonthLocalTz, DateLocalTz
    ) AS X
GROUP BY YearLocalTz, MonthLocalTz
ORDER BY YearLocalTz ASC, MonthLocalTz ASC

我的代碼中需要注意的一些事情:

  1. 我使用PERSISTED列獲取月份和年份的日期部分(因為填充表格時我很懶)
  2. 使用顯式CONVERT可以轉義CONVERT入小數的整數數學。 乘以1.0是一個不太容易理解的技巧。
  3. 使用CONVERT(DATE, ...)向下舍入到午夜,而不是在字符串之間來回轉換
  4. 通過將所有內容都設為大寫(或小寫,您的喜好)來進行不區分大小寫的字符串搜索
  5. 不要減去3毫秒來獲取午夜之前的最后一刻。 更改語義以將時間范圍的結束解釋為互斥,而不是處理數據類型的精度。 唯一的區別是使用顯式比較器(即,使用<代替<= )。 此外, DATETIME分辨率為1/300 第二的 ,而不是3毫秒。
  6. 避免將內置關鍵字用作列名(即“ TEXT”)。 如果這樣做,請將其包裝在方括號中以避免歧義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM