合并SQL语句(mssql)

时间:2014-08-06 09:29:30

标签: sql sql-server sql-server-2008 tsql sql-server-2012

我想合并这两个语句以获得7行(每天一行),并告诉我每天有多少事件和警报。如果没有,我想为每一行(日)获得一个“NULL”值。

当前的声明有效,但“事件”和“警报”在不同的行上,如果没有事件,我什么也得不到......

我想我可以使用“WITH”子句,但我有点迷失:S

SELECT 'events' as Type, 
CAST(extended_timestamp AS DATE) as DateField, 
count(*) as SumField 
FROM [dbauditor_repo].[dbo].[dbauditor_repo_events] 
WHERE extended_timestamp > (select DATEADD(day, DATEDIFF(day, 0, GETDATE())-7, 0)) 
GROUP BY CAST(extended_timestamp AS DATE) 
UNION 
SELECT 'alarms' as Type, 
CAST(extended_timestamp AS DATE) as DateField, count(*) as SumField 
FROM [dbauditor_repo].[dbo].[dbauditor_repo_events] 
WHERE extended_timestamp > (select DATEADD(day, DATEDIFF(day, 0, GETDATE())-7, 0)) 
AND returncode = 1 
GROUP BY CAST(extended_timestamp AS DATE) 
ORDER BY DateField

感谢您的帮助!

4 个答案:

答案 0 :(得分:0)

不知道表格背后的架构,并假设returncode = 1表示警报:

SELECT IIF(returncode = 1, 'alarms', 'events') as [Type]
     , CAST(extended_timestamp AS DATE) as DateField
     , count(*) as SumField 
FROM [dbauditor_repo].[dbo].[dbauditor_repo_events] 
WHERE extended_timestamp > DATEADD(day, DATEDIFF(day, 0, GETDATE())-7, 0)
GROUP BY IIF(returncode = 1, 'alarms', 'events'), CAST(extended_timestamp AS DATE) 
ORDER BY DateField

<强>更新

道歉,似乎我没有正确地阅读你的问题。您需要的是我上面的原始答案和PIVOT的组合,以平整结果集并为您提供3列。

CTE几乎相同 - 它采用数据集并计算其Type。在此之后,我们使用PIVOT将每个Type的每日计数放入其自己的列中。

declare @events table (ID int, extended_timestamp datetime, returncode int)
insert into @events values (1, dateadd(day, -6, GETDATE()), 0), (2, dateadd(day, -6, GETDATE()), 1), (3, dateadd(day, -6, GETDATE()), 1), (4, dateadd(day, -5, GETDATE()), 1);

WITH CTE AS(
    SELECT IIF(returncode = 1, 'alarms', 'events') as [Type]
         , DATEDIFF(day, 0, extended_timestamp) as DayNumber
         , count(*) as SumField 
    FROM @events
    WHERE extended_timestamp >= DATEADD(day, DATEDIFF(day, 0, GETDATE())-6, 0)
    GROUP BY IIF(returncode = 1, 'alarms', 'events'), DATEDIFF(day, 0, extended_timestamp)
)
, CTE2 AS(
    select DayNumber, [events] + [alarms] as [events], [alarms]
    from
    (select SumField, DayNumber, [Type] from CTE) as _S
    PIVOT (
        SUM(SumField)
        FOR [Type] IN ([events], [alarms])
    ) as _P
)
select cast(DATEADD(day, n.N, 0) as Date) as DateField, [events], [alarms]
from dbo.Numbers n
     left outer join CTE2 on n.N = DayNumber
where n.N between DATEDIFF(day, 0, GETDATE()) - 6 and DATEDIFF(day, 0, GETDATE())
order by 1

返回:

DateField  events      alarms
---------- ----------- -----------
2014-07-31 3           2
2014-08-01 1           1
2014-08-02 NULL        NULL
2014-08-03 NULL        NULL
2014-08-04 NULL        NULL
2014-08-05 NULL        NULL
2014-08-06 NULL        NULL

这也使用Numbers table来获取“每天1行,无论如何”要求。请注意,查询已更改为使用DayNumber,因此此连接可以尽可能干净。

答案 1 :(得分:0)

在我对我的误解之后做了很多修改之后,发现上面我的答案中的SQL真的很愚蠢。它完成了工作,但一旦正确理解,有一个更清晰的版本:

declare @events table (ID int, extended_timestamp datetime, returncode int)
insert into @events values (1, dateadd(day, -6, GETDATE()), 0), (2, dateadd(day, -6, GETDATE()), 1), (3, dateadd(day, -6, GETDATE()), 1), (4, dateadd(day, -5, GETDATE()), 1);

select cast(DATEADD(day, n.N, 0) as Date) as DateField
     , NULLIF(SUM(CASE WHEN returncode IS NOT NULL THEN 1 ELSE 0 END),0) as [events]
     , NULLIF(SUM(CASE WHEN returncode = 1 THEN 1 ELSE 0 END),0) as [alarms]
from dbo.Numbers n
     left outer join @events on n.N = DATEDIFF(day, 0, extended_timestamp)
where n.N between DATEDIFF(day, 0, GETDATE()) - 6 and DATEDIFF(day, 0, GETDATE())
group by n.N
order by 1

结果完全相同:

DateField  events      alarms
---------- ----------- -----------
2014-07-31 3           2
2014-08-01 1           1
2014-08-02 NULL        NULL
2014-08-03 NULL        NULL
2014-08-04 NULL        NULL
2014-08-05 NULL        NULL
2014-08-06 NULL        NULL

答案 2 :(得分:0)

您最初的问题是如何合并到语句或不同的数据集。

答案是你需要找到一些东西来加入它们。 UNION会将结果合并为您发现的单独行。

我认为这会做你想要的,它会在DATE对每个单独的查询进行分组,然后在同一个日期加入以显示你正在寻找的结果。

select a.DateField, a.events, b.alarms FROM 
(select CAST(extended_timestamp AS DATE) as DateField, count(*) as [events]
   FROM [dbauditor_repo].[dbo].[dbauditor_repo_events] 
   WHERE extended_timestamp > DATEADD(day,-7, getdate()) 
   GROUP BY CAST(extended_timestamp AS DATE)
) a
,(select CAST(extended_timestamp AS DATE) as DateField, count(*) as [alarms]
   FROM [dbauditor_repo].[dbo].[dbauditor_repo_events] 
   WHERE extended_timestamp > DATEADD(day, -7, getdate()) AND returncode = 1 
   GROUP BY CAST(extended_timestamp AS DATE) 
) b
where a.DateField = b.DateField
ORDER BY a.DateField

但是再一次,在审核了你的陈述后,看起来“闹钟”只是一种事件,所以我认为你可以在你的情况下选择一个选项:

SELECT DateField, max([events]) as [events], max([alarms]) as [alarms] FROM
(select CAST(extended_timestamp AS DATE) as DateField, count(*) as [events], 
       SUM(case when returncode = 1 as 1 else 0 end) as [alarms]
  FROM [dbauditor_repo].[dbo].[dbauditor_repo_events] 
  WHERE extended_timestamp > DATEADD(day, -7, getdate()) 
  GROUP BY CAST(extended_timestamp AS DATE)
UNION
select CAST(getdate() as DATE), NULL, NULL
UNION
select CAST(DATEADD(day, -1, getdate()) as DATE), NULL, NULL
UNION
select CAST(DATEADD(day, -2, getdate()) as DATE), NULL, NULL
UNION
select CAST(DATEADD(day, -3, getdate()) as DATE), NULL, NULL
UNION
select CAST(DATEADD(day, -4, getdate()) as DATE), NULL, NULL
UNION
select CAST(DATEADD(day, -5, getdate()) as DATE), NULL, NULL
UNION
select CAST(DATEADD(day, -6, getdate()) as DATE), NULL, NULL
) a
GROUP BY DateField
ORDER BY DateField

答案 3 :(得分:0)

根据您当前的查询,当returncode为1时,事件也可能是警报,因此它会对两个计数产生影响。

此查询将在同一行返回两个计数:

SELECT
  x.DateField,
  Events = COUNT(*),
  Alarms = COUNT(CASE e.returncode WHEN 1 THEN 1 END)
FROM
  [dbauditor_repo].[dbo].[dbauditor_repo_events] AS e
CROSS APPLY
  (SELECT CAST(e.extended_timestamp AS DATE)) AS x (DateField)
WHERE
  e.extended_timestamp > DATEADD(day, DATEDIFF(day, 0, GETDATE())-7, 0)
GROUP BY
  x.DateField
;

Alarms表达式使用条件聚合:它仅在e.returncode匹配1时计算行数,而Events只是&#34;计算所有行&#34;。

上述查询的唯一问题是它只返回表中表示的天数。要根据需要返回整个时间间隔的结果集,可以使用如下日历表:

SELECT
  DateField = c.Date,
  Events    = COUNT(*),
  Alarms    = COUNT(CASE returncode WHEN 1 THEN 1 END)
FROM
  [dbauditor_repo].[dbo].[dbauditor_repo_events] AS e
CROSS APPLY
  (SELECT CAST(e.extended_timestamp AS DATE)) AS x (DateField)
RIGHT JOIN
  dbo.Calendar AS c ON c.Date = x.DateField
                   AND e.extended_timestamp > DATEADD(day, DATEDIFF(day, 0, GETDATE())-7, 0)
GROUP BY
  c.Date
;

如果您没有日历表,可以轻松创建日历表&#34;即时#34;在7天的小时间内,例如使用这种方法:

SELECT
  Date = DATEADD(DAY, DayNumber, StartingDate)
FROM
  (VALUES (0), (1), (2), (3), (4), (5), (6)) AS v (DayNumber)
CROSS APPLY
  (SELECT DATEADD(DAY, -7, CAST(GETDATE() AS date))) AS x (StartingDate)
;

因此,将它与前一个查询相结合,你会得到这样的结果:

WITH Calendar AS (
  SELECT
    Date = DATEADD(DAY, DayNumber, StartingDate)
  FROM
    (VALUES (0), (1), (2), (3), (4), (5), (6)) AS v (DayNumber)
  CROSS APPLY
    (SELECT DATEADD(DAY, -7, CAST(GETDATE() AS date))) AS x (StartingDate)
)
SELECT
  DateField = c.Date,
  Events    = COUNT(*),
  Alarms    = COUNT(CASE returncode WHEN 1 THEN 1 END)
FROM
  [dbauditor_repo].[dbo].[dbauditor_repo_events] AS e
CROSS APPLY
  (SELECT CAST(e.extended_timestamp AS DATE)) AS x (DateField)
RIGHT JOIN
  Calendar AS c ON c.Date = x.DateField
               AND e.extended_timestamp > DATEADD(day, DATEDIFF(day, 0, GETDATE())-7, 0)
GROUP BY
  c.Date
;