SQL Server EXISTS查询以确定关系

时间:2012-02-23 21:03:02

标签: sql sql-server

我有以下表格:

   FooId INT PRIMARY KEY

FooRelationship

   FooRelationshipId INT PRIMARY KEY IDENTITY
   FooParentId INT FK
   FooChildId INT FK

我如何编写一个返回Foo中每个id的查询以及记录的状态(无论是父级,子级还是两者都没有)。

规则:

  • foo只会是父母或孩子,或者两者都不是。
  • foo可以是多个不同foos的父母。
  • 一个foo不能是一个以上的孩子。

我最初写了这个查询:

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

这是破坏的,因为如果Foo是另外两个Foos的父亲,那么它会返回该id两次。

如何将其重写为不使用连接或使用EXISTS或其他内容。

3 个答案:

答案 0 :(得分:2)

只需使用DISTINCT - 这是一个很好的用例。您无法使用EXISTS,因为您实际需要从两个表中提取数据:

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的忠实粉丝,因为它经常被用来隐藏凌乱的数据,但我认为这是适当的用途。

请注意,如果您在大量字段和行中使用它,可能会大大减慢速度。

如果您只想获取这些值,然后填充其余行,则可以为关系逻辑执行子查询:

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

答案 1 :(得分:0)

尝试使用SELECT DISTINCT FooID, ...

如果您提到有问题

,它将只返回一个FooID

答案 2 :(得分:0)

只需修改现有查询即可select distinct而非普通select