2008-10-09 5 views
3

"in"대신 "exists"를 사용하는 것을 (어제) 배웠습니다.SQL - 테이블 별칭 범위

BAD 
select * from table where nameid in ( 
      select nameid from othertable where otherdesc = 'SomeDesc')  
GOOD 
select * from table t where exists ( 
      select nameid from othertable o where t.nameid = o.nameid and otherdesc = 'SomeDesc')  

그리고 나는 이것에 대해 몇 가지 질문이 있습니다

1) 내가했다 이해로 설명 : 만 일치하는 값이 대규모을 구축하는 대신 반환되기 때문에 는 "이 더 나은 이유는 가능한 결과 목록 ". 첫 번째 하위 쿼리가 900 개의 결과를 반환하는 반면 두 번째 하위 쿼리는 1 (예 또는 아니요) 만 반환한다는 의미입니까?

2) 과거에는 "처음 1000 행만 검색 할 수 있습니다"라는 RDBMS가있었습니다.이 두 번째 방법으로 문제를 해결할 수 있습니까?

3) 두 번째 하위 쿼리의 별칭 범위는 무엇입니까? ... 별칭은 괄호 안에 만 있습니까? I 번째에서 (표 othertable위한 O) 동일한 가명을 사용하는 경우

select * from table t where exists ( 
      select nameid from othertable o where t.nameid = o.nameid and otherdesc = 'SomeDesc')  
AND 
      select nameid from othertable o where t.nameid = o.nameid and otherdesc = 'SomeOtherDesc')  

인지, "존재"예

그것은 제 존재에 문제를 제시 할 것인가? 아니면 완전히 독립적입니까?

오라클과 관련된 것이거나 대부분의 RDBMS에 유효합니까?

감사

+0

"존재"... 서로 호환되지 않습니다 "있다". – Constantin

+0

두 번째 쿼리는 구문 분석하지 않습니다. 텍스트에 "두 번째 존재"가 표시되므로 'AND 존재 여부 (AND는? – philipxy

답변

3

그것은 각 DBMS 고유의 쿼리 최적화 프로그램에 따라 많은. 일부 최적화 프로그램은 IN 절을 감지하여 변환합니다.

select t.* 
from table t 
join othertable o on t.nameid = o.nameid 
    and o.otherdesc in ('SomeDesc','SomeOtherDesc'); 

그리고, 귀하의 질문에 대답 :

    을 내가 테스트 한 모든 DBMS의에서

    는, 별명은 같은 쿼리를 다시 작성할 수 있습니다, BTW 제()

    내부에서만 유효합니다

1

개인적으로이 경우 하위 쿼리가 아닌 조인을 사용합니다.

SELECT t.* 
FROM yourTable t 
    INNER JOIN otherTable ot 
     ON (t.nameid = ot.nameid AND ot.otherdesc = 'SomeDesc') 
2
  1. 오라클 별 : 당신이 IN 절을 사용하여 쿼리를 작성하는 경우, 당신은 당신이 내부 쿼리가 외부 쿼리를 구동 할 규칙 기반 최적화를 말하는 것입니다. where 절에 EXISTS를 쓸 때, 내부 쿼리에서 값을 가져 오기 위해 각 값을 사용하여 외부 쿼리를 먼저 실행하도록 옵티 마이저에 지시합니다. "Difference between IN and EXISTS in subqueries"을 참조하십시오.
  2. 아마도.
  3. 하위 쿼리 내부에 선언 된 별칭은 하위 쿼리 내에 있습니다. 그건 그렇고, 난 2 ANDed 하위 쿼리와 예제는 유효한 SQL이라고 생각하지 않습니다. AND 대신 UNION을 의미 했습니까?
3

'상관 된 하위 쿼리'라고하는 복잡한 영역을 연구하고 있습니다.테이블과 키 구조에 대한 자세한 정보가 없으므로 일부 답변은 '어쩌면'일 수 있습니다.

초기 IN 쿼리에서 OtherTable에 Column NameID가 있는지 여부에 관계없이 표기법이 유효합니다 (실제로 OtherDesc가 Table 또는 OtherTable에 열로 존재하는지 여부는 귀하의 예에서는 분명하지 않지만 아마도 OtherTable의 컬럼이다). 이 동작은 상관 하위 쿼리를 상관 하위 쿼리로 만드는 역할을합니다. 우발적 인 태도로 사람을 처음 만났을 때 사람들을 위협하는 일상적인 원인이기도합니다. SQL 표준에서는 하위 쿼리에 언급 된 테이블에 관련 이름이있는 열이 없지만 하위 쿼리에 열이있는 경우 하위 쿼리의 이름을 외부 쿼리의 열을 참조하는 것으로 해석하는 동작을 요구하므로 외부 (메인) 쿼리에 언급 된 테이블에서 관련 이름을 사용하는 경우 SQL 표준 (이 비트)에 대한 적합성을 주장하려는 제품은 전혀 다른 작업을 수행하지 않습니다.

Q1에 대한 대답은 "의존적"이지만 그럴듯한 가정 (NameID는 두 테이블 모두에 열로 존재하며 OtherDesc는 OtherTable에만 존재 함)이 주어지면 결과는 반환되는 데이터 세트 측면에서 동일해야하며, 성능면에서 동등하지 않을 수 있습니다.

Q2에 대한 답은 과거에는 불량 DBMS가 아닌 DBMS를 사용하고 있었기 때문입니다. EXISTS를 지원하면 DBMS는 여전히 결과의 카디널리티에 대해 불평 할 수 있습니다.

첫 번째 EXISTS 쿼리에 적용된 Q3에 대한 대답은 "t는 문 전체에서 별칭으로 사용할 수 있지만 o는 괄호 안의 별칭으로 만 사용할 수 있습니다"입니다. 귀하의 두 번째 예제 상자에 적용 - AND 두 개의 하위 선택 (두 번째는 내가 그것을 볼 때 열린 괄호가 누락 됨)을 연결하면 "t는 문 전체에서 별칭으로 사용 가능하며 동일한 것을 참조합니다 표가 있지만 'o'라는 레이블이 붙은 두 개의 다른 별칭이 있으며 각 하위 쿼리에 하나씩 있습니다. OtherDesc가 OtherTable의 주어진 NameID 값에 대해 고유 한 경우 쿼리에서 데이터를 반환하지 않을 수 있습니다. 그렇지 않으면 동일한 NameID 및 해당 NameID 값을 가진 Table의 각 행에 대한 두 개의 OtherDesc 값을 갖는 OtherTable의 두 행이 필요합니다.

1

EXISTS가 항상 IN보다 우수하다는 것을 일반화하기는 어렵습니다. 그런 경우 논리적으로 SQL 공동체는 IN을 EXISTS로 바꿨을 것입니다 ... 또한 IN과 EXISTS는 같지 않으므로 둘을 사용할 때 결과가 다를 수 있습니다 ...

With IN, 일반적으로 NULL을 제거하지 않고 한 번 내부 테이블의 전체 테이블 검색 (내부 테이블에 NULL이있는 경우 IN은 기본적으로 NULL을 제거하지 않습니다) ... EXISTS가 NULL을 제거하고 상관 하위 쿼리의 경우에는 외부 쿼리의 모든 행에 대해 내부 쿼리를 실행합니다.

NULLS가없고 단순한 쿼리 (상관 관계 없음)가 없다고 가정하면 찾고있는 행이 마지막 행이 아니면 EXIST가 더 잘 수행 될 수 있습니다. 이 마지막 행을로 발생하면되지, ...처럼 말 .. 너무 비슷한 성능까지

를 스캔해야 할 수 있습니다 존재하지만 IN과 EXISTS는

그건