2014-11-24 3 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

+0

글쎄, 어떻게 데이터를 한 달씩 그룹화 할 수 있는지 모르겠습니다. 이것이 내가 원하는 개선점입니다. – TioDavid

+2

당신이 가지고있는 테이블 구조를 설명하지 않기 때문에 모호합니다. 그 달을 선택할 칼럼을 모를 때 월별로 그룹화하는 방법을 어떻게 알 수 있습니까? (예 : DateMsgIncome, DateMsgSent는 DateTime 열 둘 다 같습니다.) – DrCopyPaste

답변

2

코드 정리 도구를 사용하여 쿼리를 실행하여 정리를 도와줍니다. 또한 내가 말한 것을 이해하지 못했기 때문에 변수 선언을 변경합니다. 기록을 위해, 코딩 한 방식으로 지난 수 밀리 초 동안 행을 놓친 것일 수 있습니다.

DATEDIFF 함수에서 datepart 이름의 철자가 잘못 사용 되었기 때문에 DATEDIFF 함수를 변경했습니다. 잘못된 약어를 ​​사용하기가 너무 쉽기 때문입니다. 또한 마지막 열의 계산을 단순화했습니다. 1에서 1.0으로 변경하면 돈으로 변환 할 필요가 없습니다. 개체 이름에 예약어를 사용하지 말고 열 이름에 공백을 두지 마십시오. 프론트 엔드가 이런 종류의 형식화를하게하십시오.

테이블 힌트를 사용할 때 WITH 키워드가 곧 추가되었습니다. (나는 그것을 사용하기 전에 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

매우 필수적인 테이블입니다. 잠금을 방지해야합니다. 그것이 그 위에 '졸작'의 이유입니다. 나는 당신의 대답을 시험 할 것이다. 도와 줘서 고마워. – TioDavid

+0

나는 그것을 잠그고 싶지 않다. 나는 종종 힌트가 던져지고 사용자가 실제로 무엇을하는지 전혀 모르는 것을 보았습니다.누락되거나 행이 중복되거나 중복 될 수 있습니다. http://blogs.msdn.com/b/davidlean/archive/2009/04/06/sql-server-nolock-hint-other-poor-ideas.aspx –

+0

내가 필요한만큼 효과가있었습니다. 나는'where' 절 뒤에'group by '을 조정한다. 당신의 도움과 당신의 인내심에 감사드립니다. 나는 SQL이 좋지 않지만, 지금은이 보고서를 작성하는 유일한 사람입니다. 다시 감사합니다. – TioDavid