2015-04-01 56 views
1

我開發了一些SQL來生成我們的本地故障單數據庫表(SQL Server 2008)的統計信息。從我的代碼中可以看到,我想從TICKETS中選擇,加入組以獲取組名稱,按組代碼以及年/月分組。SQL生成多個計數列

我想創建總計(計數)多少張門票是打開,關閉,在sla(過期日期)之外關閉的,最終是SLA%。

此代碼有效,但我不滿意編碼所有嵌套(選擇計數);這似乎不是一個很好的策略與多次重新掃描。

是否有更好的設計來從桌面上的單個選擇生成多個「計數」列......或者這是標準方法嗎?

select g.group_name as [Group], 
     year(tm.date_open) as Year, 
     month(tm.date_open) as Month, 
     COUNT(*) as [Tickets Opened], 

     (select COUNT(*) 
     from TICKETS tm2 
     where tm2.group_code = tm.group_code 
     and year(tm2.COMPLETION_DATE) = year(tm.date_open) 
     and month(tm2.COMPLETION_DATE) = month(tm.date_open) 
     ) as [Tickets Closed], 

     (select COUNT(*) 
     from TICKETS tm2 
     where tm2.group_code = tm.group_code 
     and year(tm2.COMPLETION_DATE) = year(tm.date_open) 
     and month(tm2.COMPLETION_DATE) = month(tm.date_open) 
     and tm2.[COMPLETION_DATE] <= tm2.[DUE_DATE:] 
     ) as [Closed Within SLA], 

     (select COUNT(*) 
     from TICKETS tm2 
     where tm2.group_code = tm.group_code 
     and year(tm2.COMPLETION_DATE) = year(tm.date_open) 
     and month(tm2.COMPLETION_DATE) = month(tm.date_open) 
     and tm2.[COMPLETION_DATE] > tm2.[DUE_DATE:] 
     ) as [Closed Outside SLA] --service level agreement 


from TICKETS tm 
left join GROUPS g on g.group_code = tm.group_code 
where g.group_code in ('techs', 'reps', 'phone') 

and year(tm.date_open) = 2015 
--and month(tm.date_open) = 3 -- specific month 

group by tm.group_code, g.group_name, year(tm.date_open), month(tm.date_open) 

order by g.group_name, year(tm.date_open), month(tm.date_open) 

,我也要去想添加SLA%列將被([關閉在SLA]/[關閉門票])* 100。但是,當我看到它從我目前的設計,我會爲另一列添加冗餘嵌套SELECTS,例如...

(
    cast((select COUNT(*) 
    from TICKETS tm2 
    where tm2.group_code = tm.group_code 
    and year(tm2.COMPLETION_DATE) = year(tm.date_open) 
    and month(tm2.COMPLETION_DATE) = month(tm.date_open) 
    and tm2.[COMPLETION_DATE] <= tm2.[DUE_DATE:] 
    ) as decimal)/
    (select COUNT(*) 
    from TICKETS tm2 
    where tm2.group_code = tm.group_code 
    and year(tm2.COMPLETION_DATE) = year(tm.date_open) 
    and month(tm2.COMPLETION_DATE) = month(tm.date_open) 
    ) 
) * 100 as [SLA%] 

回答

3

是的,你可以比一堆子查詢做得更好。在單個聚合查詢中,通過計算滿足條件時評估爲1的各種表達式,可以獲得滿足不同條件的單獨行數,否則爲零。或者,您可以使用COUNT()表達式計算出您想計算的那些行的非NULL。例如,它看起來像這樣可能接近你之後:

SELECT 
    g.group_name AS [Group], 
    year(tm.date_open) as Year, 
    month(tm.date_open) as Month, 
    COUNT(*) AS [Tickets Opened], 
    COUNT(tm.completion_date) AS [Tickets Closed], 
    SUM(CASE WHEN tm.completion_date <= [DUE_DATE:] THEN 1 ELSE 0 END) 
    AS [Closed Within SLA], 
    SUM(CASE WHEN tm.completion_date > [DUE_DATE:] THEN 1 ELSE 0 END) 
    AS [Closed Outside SLA], --service level agreement 
    CAST(SUM(CASE WHEN tm.completion_date <= [DUE_DATE:] THEN 1 ELSE 0 END) 
    AS decimal)/COUNT(tm.completion_date)) AS [SLA%], 
FROM 
    tickets tm 
    LEFT JOIN GROUPS g 
    ON g.group_code = tm.group_code 
WHERE 
    g.group_code in ('techs', 'reps', 'phone') 
    and year(tm.date_open) = 2015 
    -- and month(tm.date_open) = 3 -- specific month 
GROUP BY 
    tm.group_code, 
    g.group_name, 
    year(tm.date_open), 
    month(tm.date_open) 
ORDER BY 
    g.group_name, 
    year(tm.date_open), 
    month(tm.date_open) 
+0

這很好,約翰。我按照你的例子修改了我的查詢,效果很好。這個策略對我來說是好學的。感謝那。另外要注意的是,速度的增加是巨大的。我的嵌套select語句運行了大約30秒。在修改你的方法後,我認爲有什麼不對,因爲當我運行它時,響應幾乎是立即的,不到一秒鐘!謝謝。 – Riccarr 2015-04-01 20:04:50

+0

我不確定Stackoverflow上的協議...所以雖然答案是一個很好的例子,如何重寫我的問題,並且我認爲它是完美的,經過仔細分析,結果實際上對我的情況並不準確。問題是在我的情況下,一張票可能會在一個月結束並在下個月關閉。我的原始設計將準確地包括[閉門票]計數中的那些,而在約翰的方法中,由於開放和結束的月份不同,所以錯過了這些計數。我不知道如何解釋這是這種設計? – Riccarr 2015-04-01 23:15:39

+0

@Riccarr,如果我已經充分回答了你提出的問題*,那麼你應該考慮我的答案是接受的候選人。當然,你可以像你一樣在評論中進一步討論答案。關於您觀察到的行爲差異,您可以使用我提供的技術來改變票據被視爲已關閉的條件。然而,我觀察到,我認爲你有它倒退:我提出的查詢將計數每個組中具有非'NULL'完成日期「關閉」的所有*票據;原來只計算在同一個月內完成的。 – 2015-04-02 15:54:58