2011-04-12 4 views
2

두 테이블이 있습니다 :SQL 문의 하위 쿼리 사용에 대한 대안?

TableA: (a temporary table) 
ItemId (int) 

TableB: 
ItemId (int), ParentID (int) 

표 A의 항목 중 ParentID가 ItemID로 존재하지 않는 표 A의 모든 항목을 검색하려고합니다. (즉, TableA 항목의 루트를 가져오고 싶습니다.)

이 쿼리는 내가 원하는 것을 수행합니다.

SELECT a.ItemID 
FROM TableA a 
INNER JOIN TableB b ON a.ItemId = b.ItemID 
WHERE b.ParentID NOT IN (SELECT * from TableA) 

다음과 같이하십시오.

SELECT b.ItemID 
FROM TableB b 
WHERE b.ItemID IN (SELECT * FROM TableA) 
AND b.ParentID NOT IN (SELECT * FROM TableA) 

특히 NOT IN/IN을 사용하기 때문에 쿼리의 그들없이 할 수있는 방법이 있습니까? 아마도 서브 쿼리를 필요로하지 않는 더 깨끗한 방법일까요?

샘플 데이터 :

Table A 
------- 
2 
3 
5 
6 

Table B 
-------- 
1 | NULL 
2 | 1 
3 | 1 
4 | 3 
5 | 3 
6 | 3 

원하는 결과 :

2 
3 

감사

+0

이 하위 쿼리에 위배되는 이유가 있습니까? 이 경우에는 'LEFT JOIN'보다 빨리 실행해야합니다. – JNK

+1

음, 분명히 하위 쿼리를 반복하지 않아도되는 것을 좋아합니다 ... 그렇게하는 것이 이상하게 보입니다. 그런 말을하면서, 나는 단지 그들이 나쁘다고 생각했는데 ... 그게 ... 나는 ... 모든 곳에서 읽었다. – Swati

+0

아마이 인스턴스에서 더 빨리 진행될 수있는 이유를 설명 할 수 있습니까? – Swati

답변

4

서브 쿼리없이 :

SELECT ItemID 
    FROM TableA 
INTERSECT 
SELECT b.ItemID 
    FROM TableB AS b 
     LEFT OUTER JOIN TableA AS a 
      ON b.ParentID = a.ItemID 
WHERE a.ItemID IS NULL; 

...하지만 서브 쿼리의 두려움이 합리적입니까? :) 내가 읽고 이해하기 쉽게이 해당 쿼리를 찾을 것 :

SELECT ItemID 
    FROM TableA 
INTERSECT 
SELECT ItemID 
    FROM TableB 
WHERE NOT EXISTS (
        SELECT * 
        FROM TableA AS a 
        WHERE a.ItemID = TableB.ParentID 
       ); 
+1

감사합니다 :) 그것은 비합리적 인 공포입니다, 나는 생각한다. – Swati

+0

'in (subquery) '에 대한 한 가지 두려움은'in' 절에서 가질 수있는 결과의 수의 제한이다. 사실 SQL Server 2008 r2 익스프레스의 'in' 절에 최대 2100 개의 ID 만 가질 수 있다는 오류가 발생했습니다. –

+0

@goku_da_master : 실제로는 IN (<테이블 표현식, 하위 쿼리 일 수 있음)'대신에'IN (<쉼표로 구분 된 목록>) 또는'IN (<테이블 생성자>)' 모든 구문 분석기에는 한계가 있습니다! – onedaywhen

4

를 사용하여 쿼리의이 종류를 할 수있는 5 개 가지 방법을 볼 수 Select all rows from one table that don't exist in another table에서보세요

NOT IN
NOT EX 주의자
왼쪽 및 오른쪽이
가 외부 (2005 +)

다음

제외 (2005 +)
을 적용 가입하면

CREATE TABLE #TableA(ItemId int) 

INSERT #TableA values(1) 
INSERT #TableA values(2) 
INSERT #TableA values(3) 
INSERT #TableA values(4) 
INSERT #TableA values(5) 
INSERT #TableA values(6) 


CREATE TABLE #TableB(ItemId int, ParentID int) 
INSERT #TableB values(1,1) 
INSERT #TableB values(2,2) 
INSERT #TableB values(4,3) 
INSERT #TableB values(5,4) 

이 부모를 위해 그것을 할 것입니다 실행할 수있는 스크립트입니다

SELECT a.ItemID 
FROM #TableA a 
LEFT JOIN #TableB b ON a.ItemId = b.ParentID 
WHERE b.ItemID IS NULL 

SELECT a.ItemID 
FROM #TableA a 
WHERE NOT EXISTS (SELECT 1 FROM #TableB b WHERE a.ItemId = b.ParentID) 

출력

ItemID 
5 
6 
+0

그러면 나에게 nullset이 생깁니다. 모든 항목에는 부모가 있으므로 null이 될지 확실하지 않습니다. – Swati

+0

그 중 저에게 적합한 것은 없습니다. 나는 연결된 질문이 적용 믿지 않아요 - 나는 두 테이블에 존재하는 레코드가 필요합니까 ParentID (TableB의)는 TableA의 ItemID가 아닙니다 – Swati

+0

코드를 추가했습니다 – SQLMenace

0

외부 조인을 사용할 수 있습니다. 이런 식으로 뭔가 :

SELECT a.ItemID 
FROM TableA a 
INNER JOIN TableB b ON a.ItemId = b.ItemID 
LEFT JOIN TableB parentB on a.ItemID = parentB.ParentID 
WHERE parentB.ParentID IS NULL 
0

귀하의 테이블 A와 B 것은 트리 구조를 저장하는 것 같다. 나는 테이블 A를 "노드"(트리의 요소 저장) 및 테이블 B를 "에지"(부모 노드에 연결)로 해석합니다. 내부 조인의 변형은 "부모에게는 가장자리 없음", "ParentID null로 가장자리"및 "존재하지 않는 부모와 가장자리"의 모든 사례를 한꺼번에 다루기 때문에 매우 우아합니다. 건배