2014-11-24 72 views
-5

我來完善這個查詢,工作得非常好。提高SQL Server查詢

DECLARE  @timTimeout int, 
     @iniDate varchar(20), 
     @endDate varchar(20)    
SET   @iniDate = '2014-07-20 00:00:00'    
SET   @endDate = '2014-11-24 23:59:59'   
SET   @timTimeout = 4000      

SET ANSI_WARNINGS OFF 

SELECT 
      'Approved (0200)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0200' THEN 1 END), 0), 
      'Approved Off (0220)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0220' THEN 1 END), 0), 
      'Cancel (0400)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0400' THEN 1 END), 0), 
      'Regret (0420)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0420' THEN 1 END), 0), 
      'TOTAL' = COUNT(*), 
      'Time-outs' = ISNULL(SUM(CASE WHEN DATEDIFF(ms, DateMsgIncome, DateMsgSent) > @timTimeout THEN 1 END), 0), 
      'Disponibility (%)' = (1 - CAST(ISNULL(SUM(CASE WHEN DATEDIFF(ms, DateMsgIncome, DateMsgSent) > @timTimeout THEN 1 END), 0) as money)/COUNT(*)) * 100 
FROM Message (NOLOCK) 
    WHERE DateMsgIncome BETWEEN @iniDate AND @endDate 
      AND CodMsgIncome IN ('0200', '0220', '0400', '0420', '0800', '0900', '9080', '9085') 
      AND DescMsgIncome <> '0220' 

現在,我必須準備一份總計數據按月組織的報告。

輸出disered似乎是這樣的:

 Approved (0200) | Approved Off (0220) | Cancel | Total | Time-outs | Disponibility (%) 
July | 35     15     12  62  0   100.00 
. 
. 
. 

編輯: 這是我的查詢只有一個表。

Table Message: 
DateMsgIncome date, 
DateMsgSent date, 
CodMsgIncome varchar(4), 
DescMsgIncome varchar(4), 
CodMsgAnswer int. 

任何建議是值得歡迎的。 在此先感謝。

+2

你沒有得到任何錯誤,是嗎?您想以何種方式改進該查詢?速度,美觀,還是什麼? – DrCopyPaste 2014-11-24 15:51:23

+0

嗯,我不知道如何按月分組數據。這是我想要的改進。 – TioDavid 2014-11-24 15:52:27

+2

它含糊不清,因爲你沒有描述你有什麼表格結構。我們應該如何知道如何按月分組這個月份,當時我們甚至不知道該月份選擇哪一列? (DateMsgIncome,DateMsgSent例如似乎是兩個日期時間列) – DrCopyPaste 2014-11-24 15:58:06

回答

2

我跑查詢通過代碼格式化,以幫助它清理乾淨。我也改變了變量聲明,因爲你似乎不明白我在說什麼。對於記錄來說,您對它進行編碼的方式可能會錯過一天中最後幾毫秒的某些行。

我改變了DATEDIFF函數使用闡明的日期部分的名稱,因爲它太容易使用錯誤的縮寫,搞錯了。我還簡化了最後一欄的計算。如果將1更改爲1.0,則不需要投錢。您應該避免使用保留字作爲對象名稱,並避免列名中出現空格。讓前端做這種漂亮的格式化。

我還添加了使用不久表提示時,可以與關鍵字所需。 (我建議在使用之前理解NOLOCK的真正含義)。

DECLARE @timTimeout int 
    , @iniDate date 
    , @endDate date 

SET @iniDate = '2014-07-20'    
SET @endDate = '2014-11-25'   
SET @timTimeout = 4000      

SELECT MONTH(DateMsgIncome) as MyMonthColumn 
    , 'Approved (0200)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0200' THEN 1 END), 0) 
    , 'Approved Off (0220)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0220' THEN 1 END), 0) 
    , 'Cancel (0400)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0400' THEN 1 END), 0) 
    , 'Regret (0420)' = ISNULL(SUM(CASE CodMsgIncome WHEN '0420' THEN 1 END), 0) 
    , 'TOTAL' = COUNT(*) 
    , 'Time-outs' = ISNULL(SUM(CASE WHEN DATEDIFF(MILLISECOND, DateMsgIncome, DateMsgSent) > @timTimeout THEN 1 END), 0) 
    , 'Disponibility (%)' = (1.0 - ISNULL(SUM(CASE WHEN DATEDIFF(MILLISECOND, DateMsgIncome, DateMsgSent) > @timTimeout THEN 1 END), 0)/COUNT(*)) * 100 
FROM [Message] WITH (NOLOCK) --Ack!!! I wouldn't let this fly on my system due to inconsistencies with this hint unless accuracy is not important (like 

WHERE DateMsgIncome >= @iniDate 
    AND DateMsgIncome < @endDate 
    AND CodMsgIncome IN 
    (
     '0200' 
     , '0220' 
     , '0400' 
     , '0420' 
     , '0800' 
     , '0900' 
     , '9080' 
     , '9085' 
    ) 
    AND DescMsgIncome <> '0220' 
GROUP BY MONTH(DateMsgIncome) 
+0

它是一個非常必要的表格,我必須防止鎖定它。這就是其上的一個'nolock'的原因。我會測試你的答案。感謝您的幫助。 – TioDavid 2014-11-24 16:45:37

+0

我知道你不想鎖定它。我經常會看到這種提示,用戶並沒有真正瞭解它在做什麼。它可以並將會丟失和/或重複的行。 http://blogs.msdn.com/b/davidlean/archive/2009/04/06/sql-server-nolock-hint-other-poor-ideas.aspx – 2014-11-24 16:50:24

+0

它的工作就像我需要的一樣。我只在'where'子句後面調整'group by'。感謝您的幫助和耐心。我不擅長SQL,但現在,我是唯一一個在這裏做這個報告的人。再次感謝你。 – TioDavid 2014-11-24 16:57:14