2009-12-28 4 views
0

가능한 한 효율적으로 아래 쿼리를 다시 작성해야합니다. 이 쿼리의 성능을 향상시키는 방법에 대한 제안 사항이 있습니까? t2_1 및 t2_2 열을 nullable로 설정하고 기본값을 할당 할 계획인데, 내가 "WHERE ... IN ..."섹션을 이동할 수 있도록 조인을 수정할 수있는 경우에 주로 궁금합니다. . 대신 INNER JOIN을 사용할 수 있습니까?SQL 쿼리 도움말 다시 쓰기

SELECT t1_1 FROM t1 
LEFT JOIN #t2 
ON t1.t1_3 = t2.t2_3 
WHERE ISNULL (t2.t2_1, 54) in (SELECT ParsedValue FROM tf_ToTable(@IDList1)) 
AND ISNULL (t2.t2_2, 97) IN (SELECT ParsedValue FROM tf_ToTable(@IDList2)) 
+1

ISNULL (t2.t2_1, 54) 및 ISNULL (t2.t2_2, 97)을 갖고 싶습니까? –

+0

예, 의도적으로 그 곳에 넣어졌습니다. 원래 게시물에서 언급했듯이 내가해야 할 첫 번째 작업 중 하나는 해당 열을 null이 아니며 해당 기본값으로 설정하는 것입니다. 내 주요 질문은 WHERE IN 절이 없도록 어떻게 조인을 다시 구성 할 수 있습니다. 당신이 도움이된다면 튜닝 관점에서 IS NULL을 무시할 수 있습니다. –

+1

튜닝 관점의 문제가 아닙니다. "IS NULL"은 "ISNULL"과 많이 다릅니다. 첫 번째 구문 분석하지 않습니다. –

답변

0

아래의 쿼리를 생각하고 t2_1 및 t2_2를 기본값으로 nullable로 변경하면 성능이 가장 좋아집니다. 어떻게 생각합니까? 이것이 인덱스의 최상의 활용을 허용하지 않습니까?

SELECT t1_1 FROM t1 
LEFT JOIN #t2 ON t1.t1_3 = t2.t2_3 
INNER JOIN tf_ToTable(@IDList1) x_1 ON t2.t2_1 = x_1.ParsedValue 
INNER JOIN tf_ToTable(@IDList2) x_2 ON t2.t2_2 = x_2.ParsedValue 
0

t1.t1_3을 nullable로 만들지 않으면 왼쪽 결합을 내부 결합으로 바꿀 수 있습니다.

+0

나는 그것이 옳은 것인지 잘 모르겠다. 다음을 고려하십시오. # t2에 해당 레코드가없는 t1 레코드가 있습니다. null이 아니기 때문에 일치하지 않습니다. 귀하의 논리를 사용하여 내 쿼리에 포함될 때 해당 레코드가 제외되지 않습니까? –

1
SELECT t1_1 
FROM #t2 
JOIN t1 
ON  t1.t1_3 = t2.t2_3 
WHERE t2.t2_1 = @IDList1 
     AND t2.t2_2 = @IDList2 
UNION ALL 
SELECT t1_1 
FROM t1 
WHERE @IDList1 = 54 
     AND @IDList2 = 97 
     AND t1_3 NOT IN 
     (
     SELECT t2_3 
     FROM #t2 
     ) 
+0

+1 : Sargable 및 ISNULL (또는 COALESCE)은 색인을 사용할 수 없음을 의미합니다. –

0

@ IDList1 및 @ IDList2가 쉼표로 구분 된 문자열 인 경우,이 쿼리는 전혀 작동하지 않습니다. 테이블 변수 인 경우 IN 변수가 작동하도록 테이블 변수에서 SELECT를 가져야합니다.

공개 포럼에 질문을 올리므로 무고한 사람을 보호하기 위해 테이블 ​​이름과 열 이름이 변경되기를 바랍니다. t1_1, t1_2 등의 열 이름은 명명 규칙이 적용되는 한 꽤 끔찍합니다.

처음에 질문을 오해 한 것 같습니다. 이 구분 된 문자열 값을 찾는 특정 경우라면,

SELECT 
    T1.t1_1 
FROM 
    T1 
LEFT JOIN #t2 T2 ON 
    T2.t2_3 = T1.t1_3 
WHERE 
    EXISTS 
    (
      SELECT 
       ParsedValue 
      FROM 
       tf_ToTable(@IDList1) 
      WHERE 
       ParsedValue = ISNULL(T2.t2_1, 54) 
    ) AND 
    EXISTS 
    (
      SELECT 
       ParsedValue 
      FROM 
       tf_ToTable(@IDList2) 
      WHERE 
       ParsedValue = ISNULL(T2.t2_2, 97) 
    ) 

또는 : 여기에 두 가지 가능한 솔루션이

SELECT 
    T1.t1_1 
FROM 
    T1 
LEFT JOIN #t2 T2 ON 
    T2.t2_3 = T1.t1_3 
WHERE 
    ',' + @IDList1 + ',' LIKE '%,' + CAST(ISNULL(T2.t2_1, 54) AS VARCHAR) + ',%' AND 
    ',' + @IDList2 + ',' LIKE '%,' + CAST(ISNULL(T2.t2_2, 97) AS VARCHAR) + ',%' 

이 마지막 쿼리는 같은 쉼표를 사용하고 있다고 가정하여 문자열에 공백이 없음을 나타냅니다. REPLACE 함수를 사용하여 문자열에 공백을 제거 할 수 있습니다.

+0

idList 변수는 쉼표로 검색되는 문자열입니다. 내 실제 예제에서는 이러한 테이블로 구문 분석하는 테이블 함수가 있습니다. 이 변경 사항을 예제에 추가했습니다. 무고한 사람을 보호하기 위해 이름이 변경되었습니다. 나는 t1_1과 t1_2가 끔찍한 명명 규칙에 동의한다. 죄송합니다. 제가 처음 생각한 것입니다. –

0

이와 같은 목록을 제공하려면 Reporting Services를 사용해야합니다. 즉, 동적 SQL을 사용하여 목록을 작성해야합니다.

t2_1 및 t2_2가 NULL을 허용하지 않도록 설정하는 경우 LEFT JOIN 때문에 NULL이 유일한 시간입니다.

또한 t2_3이 고유한지 여부와 t1_3이 해당 테이블의 외래 키인지 여부 및 t1_3이 NULL을 허용 할 수 있는지 여부를 고려하십시오. # t2는 임시 테이블이므로이 경우는 아닐 것입니다.

ISNULL 문을 제거하면 도움이됩니다.

물론 색인 생성을 잊지 말고 테이블이 얼마나 큰지 생각하십시오. 여기에는 많은 요소가 관련되어 있습니다.

+0

내가 필요한 모든 인덱스를 가지고 있다고 생각하지만 ISNULL 또는 WHERE 절을 사용하면 인덱스가 올바르게 또는 전혀 사용되지 않을 것임을 이해할 수 있습니다. 그게 내가 그들을 조인으로 이동시키는 방법을 찾는 이유입니다. –

+0

반드시 JOIN 할 필요는 없습니다. 쿼리 최적화 프로그램은 WHERE 절과 JOIN 절을 비슷한 방식으로 변환합니다. "NULL은 무엇을 의미합니까?", "UNION ALL에 더 적합할까요?", "올바른 인덱스는 해시/루프 조인 대신 병합 조인이 수행된다는 의미입니까? ","Lookups를 피할 수 있습니까? "등이 있습니다. –