2009-08-17 4 views
2

최적화 할 SQL 코드가 있습니다. 코드에는 실행하기에 다소 비싼 뷰가 있습니다. 이 질문을 위해 ExpensiveView라고 부르 자. 뷰의 맨 위에는 두 개의 하위 쿼리를 통해 자체 뷰에 조인하는 쿼리가 있습니다. 예를 들어SQL 쿼리에 대한 도움말 최적화

:

select v1.varCharCol1, v1.intCol, v2.intCol from (
    select someId, varCharCol1, intCol from ExpensiveView where rank=1 
) as v1 inner join (
    select someId, intCol from ExpensiveView where rank=2 
) as v2 on v1.someId = v2.someId 

예제 결과 집합 :

some random string, 5, 10 
other random string, 15, 15 

이 작동하지만, 내가 두 번 ExpensiveView에서 선택하지 못했습니다 느리다. 내가하고 싶은 건 ExpextView에서 한 번만 선택하기 위해 case 문을 사용하는 것이다. 예를 들어

:

select someId, 
    case when rank = 1 then intCol else 0 end as rank1IntCol, 
    case when rank = 2 then intCol else 0 end as rank2IntCol 
from ExpensiveView where rank in (1,2) 

나는 그 그룹 someId하여 위의 결과는 얻을 수 거의 첫 번째 쿼리와 같은 일 :

select sum(rank1IntCol), sum(rank2Intcol) 
from (*the above query*) SubQueryData 
group by someId 

문제는 varCharCol1입니다 I 순위가 1 인 경우 순위 순위 2

입니다 때보다 1 때 열이 서로 다른 값을 포함하기 때문에 내가 그룹에서 사용할 수 없습니다 얻을 필요

누구나 쿼리를 최적화 할 수있는 솔루션이 있습니까? 그렇다면 ExpensiveView에서 한 번만 선택하고 여전히 varchar 데이터를 가져올 수 있습니까?

미리 감사드립니다.

답변

3

우리가보기 정의를 볼 수 있지만,이 시도하지 않기 때문에 추측하기 어렵다 :

SELECT MIN(CASE rank WHEN 1 THEN v1.varCharCol1 ELSE NULL END), 
     SUM(CASE rank WHEN 1 THEN rank1IntCol ELSE 0 END), 
     SUM(CASE rank WHEN 2 THEN rank2IntCol ELSE 0 END) 
FROM query 
GROUP BY 
     someId 

참고가이 같은 쿼리에 대한 대부분의 경우 :

SELECT * 
FROM mytable1 m1 
JOIN mytable1 m2 
ON  … 

SQL Server 최적화 아마도 이러한 트릭 중복 그래서 그냥 나중에 JOIN 조건 검색에 사용되는 것 Eager Spool (임시 인덱스)를 구축 할 것입니다. 널 (null)가 포함 된 VARCHAR에 대해 MIN을 사용하는 경우

+0

에 분() 또는 최대를 사용하여 NULL을 무시입니까? – bugfixr

+0

'@ Chu' : 예. – Quassnoi

+0

그래, 구현하고 잘 작동합니다! 이전 쿼리에서 515 개의 행을 반환하는 데 6 초가 걸렸습니다. 케이스를 사용하면 몇 밀리 초가됩니다. Eagar 스풀링 소개 ... 난 이유를 모르겠어,하지만 SQL Server가 원래 쿼리에 열망 스풀링을 수행하지 않은 것 같다. 아마도 쿼리가 실제로 또는 where 절이 그것을 망칠 정도로 하위 쿼리라는 사실과 관련이 있습니다. 어쨌든 팁 주셔서 감사합니다! – bugfixr

0
select someId, 
    case when rank = 1 then varCharCol1 else '_' as varCharCol1 
    case when rank = 1 then intCol else 0 end as rank1IntCol, 
    case when rank = 2 then intCol else 0 end as rank2IntCol 
from ExpensiveView where rank in (1,2) 

다음 바깥 쪽 쿼리