2011-09-02 2 views
1

다음과 같은 쿼리가 있습니다. 실행할 때대문자와 소문자가 사용 된 경우의 orderby 변환 오류

데이터 형식을 nvarchar로 숫자 변환하는 중 오류가 발생했습니다.

@sortorder = 1 또는 -1을 이름순으로 정렬 한 경우에만 발생합니다. 그러나 case 문을 제거하고 단지 order by Name asc을 사용하면 오류없이 쿼리가 실행됩니다.

아무도 설명하지 못하겠습니까? 감사.

DECLARE @SortOrder INT = 1 

CREATE TABLE #Results 
(
ID INT IDENTITY(1,1), 

NameID INT, 

Expected NUMERIC(5,1), 

Actual NUMERIC(5,1) 

) 

SELECT Name, Expected, Actual, ID 

FROM (

     SELECT ISNULL(NULLIF(Words.Word, ''), Name.Primary) AS [Name], #Results.Expected, #Results.Actual, #Results.NameID 
    FROM #Results 
    INNER JOIN Name ON Name.ID = #results.NameID 
    LEFT OUTER JOIN Words ON Name.WordID = Words.WordID 
     AND Words.LanguageID = 0 
    UNION 
    SELECT 'AVG' AS Name, 
      CAST(((SUM(#Results.Expected))/COUNT(#Results.ID)) AS NUMERIC(5,1)) AS [Expected], 
      CAST(((SUM(Actual))/COUNT(ID)) AS NUMERIC(5,1))AS [Actual], 
      -9999 as [ID] 
    FROM #Results 
) AS Results 

ORDER BY 
    CASE @SortOrder 

     WHEN 1 THEN Name  
     WHEN 2 THEN Expected 
     WHEN 3 THEN Actual  
     END ASC,  
    CASE @SortOrder 
     WHEN -1 THEN Name 
     WHEN -2 THEN Expected 
     WHEN -3 THEN Actual 
     END DESC 

답변

3

일반적으로 이와 같은 것을 사용하지 마십시오.

if @SortOrder = 1 then 
select ... order by Name; 
else if @SortOrder = 2 then 
select ... order by Expected 
else if @SortOrder = 3 then 
select ... order by Actual; 

는 당신이 지금하고있는 것은 SQL Server 쿼리 최적화에게 효율적인 계획을 마련하기 위해 어떤 점잖은 기회를 거부 할 수있는 100 % 확실한 방법입니다 : 세 가지 별도의 쿼리를 사용하여 생성 된 계획은 을 위해 일한다 any @SortOrder 변수의 값이므로 이 인덱스가 제약 조건을 만족시킬지라도 정렬을 수행해야합니다. 주제에 대한 더 자세한 토론은 Dynamic Search Conditions in T-SQL을 참조하십시오.

이제 #temp 테이블에서 오는 데이터가 스택 위로 높은 사례를 구분하는 것이 더 중요합니다. #temp 테이블은 인덱스를 지원하기 때문에 #temp 테이블을 만들 때 #temp 테이블 자체에 적절한 클러스터 된 인덱스를 추가하십시오. 특정 요구 사항에 따라 Name, Expected 또는 Actual 주문에 대해 개별 #temp 테이블을 사용한다는 것을 의미합니다.

+0

+1 이것은 물론 최고의 대답이다. –

+0

나는'exec sp_executeSQL'으로 오히려 역동적 인 SQL을 사용하여 별도의 계획을 가질 가능성이 있다고 생각합니다. 제안 된대로 'IF'를 사용하고 6 가지 다른 버전의 기본 쿼리를 유지해야합니다. –

+0

감사합니다. 내 문제를 혼란시킬뿐만 아니라 해결책을 설명했다. 너 선생님/엄마가 왜 내가 여기 와서 도움을 청하니? – 5n0u7

1

전체 CASE 발현은 highest precedence으로 분기의 데이터 형식으로 강제한다.

sql_variant으로 캐스팅 해 볼 수 있습니다. UDT를 제외한 모든 것보다 우선 순위가 높으며 올바르게 정렬해야합니다.

+1

... 'CASE' 문에서 참조되는 다른 모든 열이 동일한 유형인지 확인하십시오. 즉,'VARCHAR '또는'INT '이든간에 다른 유형을 혼합하지 마십시오 ..... –

+0

감사합니다 당신을 위해 formating하고 당신의 대답, 성공에 감사드립니다! booooooo 캔트 다른 5 분을 받아 들인다 – 5n0u7

3

잠재적 인 데이터 형식마다 별도의 case식이 필요합니다.

ORDER BY 
    CASE @SortOrder 
     WHEN 1 THEN Name END, 
    CASE @SortOrder 
     WHEN 2 THEN Expected 
     WHEN 3 THEN Actual  
     END,  
    CASE @SortOrder 
     WHEN -1 THEN Name END DESC, 
    CASE @SortOrder 
     WHEN -2 THEN Expected 
     WHEN -3 THEN Actual 
     END DESC; 
관련 문제