2012-02-23 3 views
1

나는 다음과 같은 테이블이 한을 결정하기 위해 쿼리를 EXISTS Foo의 id와 레코드의 상태 (부모인지 자식인지 또는 둘 다 아님).SQL 서버의 관계를

규칙, • foo는 단지 부모 나 자녀 또는도 될 것

  • .
  • foo는 여러 다른 foos의 부모가 될 수 있습니다.
  • foo는 둘 이상의 foo의 하위 일 수 없습니다.

    이는 푸 다른 두 FOOS에 부모 때문에 경우 고장
    SELECT 
        FooId, 
        CASE 
         WHEN Parent.FooRelationshipId IS NOT NULL THEN 'Parent' 
         WHEN Child.FooRelationshipId IS NOT NULL THEN 'Child' 
         ELSE 'Neither' 
        END 
    FROM Foo F 
    LEFT JOIN FooRelationship Parent ON F.FooId = Parent.FooParentId 
    LEFT JOIN FooRelationship Child ON F.Fooid = Child.FooParentId 
    

    다음은 그 ID를 두 번 반환

나는 원래이 쿼리를 썼다.

어떻게 이것을 조인을 사용하거나 EXISTS 등을 사용하지 않도록 다시 작성할 수 있습니까?

답변

2

그냥 DISTINCT을 사용하십시오. 좋은 사례입니다.

SELECT DISTINCT 
    FooId, 
    CASE 
     WHEN Parent.FooRelationshipId IS NOT NULL THEN 'Parent' 
     WHEN Child.FooRelationshipId IS NOT NULL THEN 'Child' 
     ELSE 'Neither' 
    END 
FROM Foo F 
LEFT JOIN FooRelationship Parent ON F.FooId = Parent.FooParentId 
LEFT JOIN FooRelationship Child ON F.Fooid = Child.FooParentId 

을 내가 정상적으로 종종 지저분한 데이터를 숨기는 데 사용하지만 있기 때문에 DISTINCT의 큰 팬이는 생각하고 있지 않다 : 당신은 실제로 두 테이블에서 데이터를 끌어 할 필요가 있기 때문에 당신은 EXISTS을 사용할 수 없습니다 그것에 대한 적절한 사용.

많은 수의 필드와 행에서 사용하는 경우 속도가 크게 저하 될 수 있음을 유념하십시오.

그냥이 값을 가져온 다음뿐만 아니라 행의 나머지 부분을 채울하려는 경우에는 관계 로직 서브 쿼리 수행 할 수 있습니다

SELECT s.FooID, s.Relationship, T.* 
FROM Table T 
INNER JOIN (SELECT DISTINCT 
    FooId, 
    CASE 
     WHEN Parent.FooRelationshipId IS NOT NULL THEN 'Parent' 
     WHEN Child.FooRelationshipId IS NOT NULL THEN 'Child' 
     ELSE 'Neither' 
    END as [Relationship] 
    FROM Foo F 
    LEFT JOIN FooRelationship Parent ON F.FooId = Parent.FooParentId 
    LEFT JOIN FooRelationship Child ON F.Fooid = Child.FooParentId) s 
ON s.FooId = t.FooID 
+0

이 쿼리를 작성하는 더 좋은 방법이 있습니까? 이 테이블에는 몇 개의 행이 있고 30-40 개의 열이 있기 때문에 성능에 대해 걱정이됩니까? – Dismissile

+0

@Dismissile 더 많은 정보가 필요 하겠지만, 하나의 옵션은 예제 (좁은) 쿼리를 subselect로 사용하고 JOIN하는 것입니다. 그러면'FooID, Relationship' 정보를 나머지 행을 얻지 않고 얻을 수 있고,'JOIN'을 사용하면됩니다. 나는 그 예를 올릴 것이다. – JNK

+0

감사합니다. 덕분에 많은 도움이되었습니다. – Dismissile

0

시도가 사용을 SELECT DISTINCT FooID, ...

는 것 문제가 있다고 언급 한 경우 FooID을 반환하십시오.

+0

'FooID'뿐만 아니라 실제로 행 값의 고유 한 조합 당 하나의 행만 반환합니다. – JNK

0

select 대신 select distinct을 수행하도록 기존 쿼리를 수정하십시오.