문제

방금 (어제) "in"대신 "Exist"를 사용하는 법을 배웠습니다.

 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) 과거에 나는 RDBMS가 불만을 가졌다.

3) 두 번째 하위 쿼리의 별칭의 범위는 무엇입니까? ... 별칭은 괄호 안에만 살아 있습니까?

예를 들어

 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' )      

즉, 두 번째 "존재"에서 동일한 별칭 (O Table OtherTable의 O)을 사용하면 첫 번째 존재와 관련된 문제가 있습니까? 아니면 완전히 독립적입니까?

이것은 Oracle이 관련이 있습니까? 아니면 대부분의 RDBM에 유효합니까?

정말 감사합니다

도움이 되었습니까?

해결책

각 DBM에 따라 다르며 쿼리 최적화에 따라 다릅니다. 일부 최적화제는 절에서 감지하여 번역합니다.

내가 테스트 한 모든 dbmses에서, 별명은 () 내부에서만 유효합니다.

BTW, 쿼리를 다시 작성할 수 있습니다.

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

그리고 당신의 질문에 답하기 위해 :

다른 팁

당신은 '상관 된 하위 쿼리'로 알려진 복잡한 영역으로 밟고 있습니다. 테이블과 주요 구조에 대한 자세한 정보가 없으므로 일부 답변은 '아마도'일 수 있습니다.

쿼리의 초기에, 표기법은 OtherTable이 열 NameDID를 포함하는지 여부에 관계없이 유효합니다 (실제로 다른 예제는 테이블의 열로 존재하는지 또는 기타 테이블로 존재하는지 여부는 예제 중 어느 것도 명확하지 않지만 아마도 열일 것입니다. 다른 테이블). 이 동작은 상관 된 하위 정체를 상관 관계 하위 쿼리로 만드는 이유입니다. 그것은 또한 사람들이 처음으로 뛰어들 때 일상적인 분노의 원천입니다. SQL 표준은 하위 쿼리에 언급 된 테이블에 관련 이름이있는 열이없는 경우 외부 쿼리의 열을 참조하는 서브 쿼리에서 이름을 해석하는 동작을 의무화하기 때문에 외부 (메인) 쿼리에 언급 된 테이블의 관련 이름, SQL 표준에 대한 준수를 주장하려는 제품은 다른 일을 수행하지 않습니다.

Q1에 대한 답은 "의존적"이지만, 그럴듯한 가정이 주어지면 (Nameid는 두 테이블의 열로 존재합니다. Otherdesc는 Othertable에서만 존재합니다) 결과는 반환 된 데이터 세트의 관점에서 동일해야합니다. 성능 측면에서 동일합니다.

Q2에 대한 대답은 과거에 결함이없는 DBMS를 사용하지 않은 경우 열등한 것을 사용했다는 것입니다. 지원되는 경우 DBMS는 여전히 결과의 카디널리티에 대해 불평 할 수 있습니다.

첫 번째 쿼리에 적용되는 Q3에 대한 답변은 "진술 전체에 걸쳐 A가 별명으로 제공되지만 O는 괄호 안에 별명으로 만 사용할 수 있습니다"입니다. 두 번째 예제 상자에 적용되는대로 두 개의 하위 선택 사항 (두 번째는 내가 볼 때 열린 괄호가 없음)을 사용하여 "T는 문 전체에서 별칭으로 사용할 수 있으며 동일하게 나타냅니다. 표이지만 'O'라는 라벨이 붙은 두 가지 다른 별칭이 있습니다. OtherDesc가 OtherTable에서 주어진 NameID 값에 대해 고유 한 경우 쿼리는 데이터를 반환 할 수 없습니다. 그렇지 않으면, 동일한 nameID와 함께 다른 행에 두 개의 행이 필요하고 해당 NameID 값이있는 테이블의 각 행에 대해 두 개의 다른 행이 필요합니다.

  1. Oracle-Specific : in clause를 사용하여 쿼리를 작성하면 규칙 기반 Optimizer에 내부 쿼리가 외부 쿼리를 구동하려는 것을 알려줍니다. WHERE 절에 쓰는 경우 각 값을 사용하여 내부 쿼리에서 값을 가져 오기 위해 외부 쿼리가 먼저 실행되기를 원하는 Optimizer에 알려줍니다. 보다 "하위 쿼리에 In과 Sivers 간의 차이".
  2. 아마.
  3. 별명은 하위 쿼리 내부에서 내부에서 선언했다. 그건 그렇고, 나는 당신의 예제가 2와 서브 쿼리를 가진 당신의 예가 유효한 SQL이라고 생각하지 않습니다. 대신 연합을 의미 했습니까?

개인적으로 나는 이것에 대한 하위 퀘스트가 아니라 조인을 사용할 것입니다.

SELECT t.*
FROM yourTable t
    INNER JOIN otherTable ot
        ON (t.nameid = ot.nameid AND ot.otherdesc = 'SomeDesc')

존재하는 것이 항상 In보다 낫다는 일반화하기가 어렵습니다. 논리적으로 그렇다면 SQL 커뮤니티가 존재하는 것으로 대체했을 것입니다 ... 또한, 존재하고 존재하는 것이 동일하지 않으며, 두 가지를 사용할 때 결과가 다를 수 있습니다 ...

ins를 사용하면 일반적으로 널을 제거하지 않고 내부 테이블의 전체 테이블 스캔 (내부 테이블에 널이있는 경우 기본적으로 널을 제거하지 않습니다) ... 존재하는 동안 널을 제거하고 하위 퀘스트의 경우에는 상관 관계가 있습니다. 외부 쿼리의 모든 행에 대한 내부 쿼리를 실행합니다.

널이없고 간단한 쿼리 (상관 관계가없는)가 있다고 가정하면, 찾는 행이 마지막 행이 아닌 경우 더 잘 수행 될 수 있습니다. 그것이 마지막 행 인 경우, 끝날 때까지 스캔해야 할 수도 있습니다. 너무 비슷한 성능 ...

그러나 존재하는 것은 상호 교환 할 수 없습니다 ...

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top