在SQL查询中查找日期的出现次数

时间:2016-12-02 08:40:23

标签: sql-server group-by

我有以下简化表:

Create table Services (
  ServiceID   int        not null,
  Created     Datetime   null,
  Authorised  DateTime   null,
  Closed      Datetime   null)

如何按月分组DateTime字段,以计算在特定月份创建,授权或关闭的服务数量?

这是我要找的结果:

Month Year   Created   Authorised   Closed
 08    2016     10         12         3
 09    2016     12          4         9
 10    2016      7          9         6
...
...

我无法找出GroupBy语句来实现这一点,即使它看起来很简单。有人可以帮忙吗?

3 个答案:

答案 0 :(得分:1)

您可以分别选择每月创建的计数,每月的授权计数和每月的已关闭计数,并完全外部加入三个。

不幸的是,SQL-Server没有标准SQL的JOIN table USING (columns),因此完全外连接,特别是涉及两个以上的表,看起来很笨拙。

select 
  coalesce(closed.mon, created.mon, authorised.mon) as [Month],
  coalesce(closed.yr, created.yr, authorised.yr) as [Year],
  created.cnt as [Created],
  created.cnt as [Authorised],
  authorised.cnt as [Closed]
from
(
  select month(created) as mon, year(created) as yr, count(*) as cnt
  from services
  group by month(created), year(created)
) created
full outer join
(
  select month(authorised) as mon, year(authorised) as yr, count(*) as cnt
  from services
  group by month(authorised), year(authorised)
) authorised on authorised.mon = created.mon and authorised.yr = created.yr
full outer join
(
  select month(closed) as mon, year(closed) as yr, count(*) as cnt
  from services
  group by month(closed), year(closed)
) closed on  closed.mon = coalesce(created.mon, authorised.mon)
         and closed.yr = coalesce(authorised.yr, created.yr);

答案 1 :(得分:1)

;WITH CTECR (Y, M) AS (
    SELECT 
        DATEPART(Year, Created), 
        DATEPART(Month, Created)
    FROM [Services]
),
CTEA (Y, M) AS (
    SELECT 
        DATEPART(Year, Authorised), 
        DATEPART(Month, Authorised)
    FROM [Services]
),
CTECL (Y, M) AS (
    SELECT 
        DATEPART(Year, Closed), 
        DATEPART(Month, Closed)
    FROM [Services]
)
SELECT M, Y, ISNULL(Created, 0), ISNULL(Authorised, 0), ISNULL(Closed, 0) FROM (
SELECT M, Y, COUNT(*) AS 'Cnt', 'Created' AS 'Evt' FROM CTECR GROUP BY M, Y
UNION ALL 
SELECT M, Y, COUNT(*), 'Authorised' FROM CTEA GROUP BY M, Y
UNION ALL 
SELECT M, Y, COUNT(*), 'Closed' FROM CTECL GROUP BY M, Y
) A
PIVOT (
    SUM(Cnt) 
    FOR Evt IN (Created, Authorised, Closed)
) AS PivotTable;

答案 2 :(得分:0)

我尝试使用分组集。 样本数据 -

declare @temp table (
    ServiceID       int         not null,
    Created         Datetime    null,
    Authorised      DateTime    null,
    Closed          Datetime    null
)

insert into @temp
select 1, '2016-08-03', '2016-07-03', '2016-02-03' union
select 2, '2016-10-03', '2016-04-03', '2016-08-03' union
select 3, '2016-04-03', '2016-02-03', '2016-12-03' union
select 4, '2016-04-03', '2016-01-03', '2016-10-03'

实际代码 -

;with grouped as (
select  created     = format(created, 'yyyyMM'),
        authorised  = format(authorised, 'yyyyMM'),
        closed      = format(closed, 'yyyyMM'),
        count_val   = count(*)
from @temp
group by grouping sets(
            format(created, 'yyyyMM'),
            format(authorised, 'yyyyMM'),
            format(closed, 'yyyyMM'))
)
,combined as(
select [Month]=right(created,2),[year]=left(created,4), created=count_val, authorised, closed
from grouped
where created is not null
union all
select [Month]=right(authorised,2),[year]=left(authorised,4), created, authorised=count_val, closed
from grouped
where authorised is not null
union all
select [Month]=right(closed,2),[year]=left(closed,4), created, authorised, closed=count_val
from grouped
where closed is not null
)
select [Month],[year],created=sum(created),authroised=sum(authorised),closed=sum(closed)
from combined
group by [Month],[year]