2016-12-02 88 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]