每天计算一次事件的发生次数

时间:2018-07-19 14:42:16

标签: tsql

正在从具有或多或少具有这种布局的表中寻找真正的快速而肮脏的数据转储...

  ID  |  EventType  | EventDate
------+-------------+------------
   1  |  Inbound    | 2018-07-18 00:00:00
   2  |  Outbound   | 2018-07-18 12:00:00
   3  |  Inbound    | 2018-07-19 00:12:00
   4  |  Failure    | 2018-07-19 00:12:00
   5  |  Inbound    | 2018-07-19 00:12:00
   6  |  Outbound   | 2018-07-19 00:12:00
      |             |

我想要的是一个查询,它每天查询一次每次出现的次数。所以“ 2018-07-19”会让我吐痰

  Failures | Inbounds | Outbounds
-----------+----------+------------
      1    |    2     |     1

这是我真正的尝试,但我认为有一种更轻松的方法来摆脱它。理想情况下,我可以将其拖放到视图中并按日期自行过滤,但是如果我需要在存储过程中传递目标日期,那很好。

我的数据库中只有3种已定义的事件类型,因此我对每一种进行计数的静态解决方案就可以了。动态地适应各种不同事件类型的方法会更好,但不是必须的

DECLARE @TestDate datetime2 = '2018-07-19 08:41:55'

SELECT 
    'Failures' = SUM(Failures), 
    'Inbounds' = SUM(Inbounds), 
    'Outbounds'= SUM(Outbounds)
FROM (
    SELECT 'Failures' = COUNT(ID), 'Inbounds' = 0, 'Outbounds' = 0 FROM tblTests WHERE EventType = 'Failed' AND EventDate BETWEEN CAST(@TestDate AS DATE)   AND DATEADD(DAY, 1, CAST(@TestDate AS DATE))    UNION
    SELECT 'Failures' = 0, 'Inbounds' = COUNT(ID), 'Outbounds' = 0 FROM tblTests WHERE EventType = 'Inbound' AND EventDate BETWEEN CAST(@TestDate AS DATE)  AND DATEADD(DAY, 1, CAST(@TestDate AS DATE))    UNION
    SELECT 'Failures' = 0, 'Inbounds' = 0, 'Outbounds' = COUNT(ID) FROM tblTests WHERE EventType = 'Outbound' AND EventDate BETWEEN CAST(@TestDate AS DATE) AND DATEADD(DAY, 1, CAST(@TestDate AS DATE))
) FIO

3 个答案:

答案 0 :(得分:1)

执行此类操作的简单方法称为条件聚合:

   https://github.com/redtempo/dnnstuff.aggregator

答案 1 :(得分:1)

在我看来,这将是一个使用计数总计的枢轴的绝佳机会。 下面的示例逐步创建了一个测试表,将OP原始问题中的数据加载到该表中,并将结果按日期排列

创建测试表

create table testtable (id int, value varchar(20), dt datetime)

将临时数据加载到新表中

insert into testtable 
values(  1,    'Inbound', '2018-07-18 00:00:00'),
   (2,    'Outbound',    '2018-07-18 12:00:00'),
   (3,    'Inbound' ,    '2018-07-19 00:12:00'),
   (4,    'Failure'  ,   '2018-07-19 00:12:00'),
   (5,    'Inbound'   ,  '2018-07-19 00:12:00'),
   (6,    'Outbound'   , '2018-07-19 00:12:00')

将数据透视正确的结果

select * from (
select value, cast(dt as date) d  
from testtable )a
pivot(
count(value) for value in ([Inbound],[Outbound],[Failure]))piv    

这将返回结果作为结果

results of sql query

可以通过在枢轴中添加其他值来轻松扩展此范围。

答案 2 :(得分:0)

这就是您需要的

SELECT EventType, COUNT(1) AS Cnt, CONVERT(DATE, EventDate) AS EventDate
FROM dbo.tblTests       
GROUP BY EventType, CONVERT(DATE, EventDate)

您可以输入WHERE以将结果限制为特定日期。 如果您打算经常运行它并在大表上运行它,建议您创建一个仅包含日期的计算的持久性列,

您可以这样做:

ALTER TABLE tblTests ADD DateOnly AS CONVERT(DATE, EventDate) PERSISTED NOT NULL

然后在上述查询中使用DateOnly代替CONVERT(DATE, EventDate)

为了获得最佳性能,您可以在EventType和新的DateOnly列上创建索引 像这样:

CREATE NONCLUSTERED INDEX [NCI_tblTest__EventType__DateOnly] ON [dbo].[tblTests]
(
    [EventType] ASC,
    [DateOnly ] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)

并记住要定期重建索引。

编辑: 这将在单独的行上为您提供不同的事件类型。

EDIT2:使用PIVOT以与所需完全相同的方式产生结果。留给您锻炼:) https://docs.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-2017