2016-12-02 89 views
0

我有以下简化表:查找SQL查询日期的出现

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

我怎么能集团的日期时间字段按月份来算有多少服务创建,授权或关闭特定月?

这就是我要寻找的结果:

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

我无法找出的GroupBy语句来实现这一点,即使它看起来很简单。谁能帮忙?

回答

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); 
+0

哇。这是少数。我需要看看是否可以修改,因为我的真正表格实际上有更多的日期/时间列。它看起来不是一个好主意,使8全外连接! – navigator

+0

不要太担心。数据库管理系统是做这种事情的。它可能在这里使用散列连接,这应该很快。请记住,只有少数记录需要连接,因为数据已经汇总。 –

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; 
+0

这看起来很有希望,但我在实际表格中还有其他分组列的日期/时间列。我会试着看看这对我是否可行。谢谢! – navigator

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]