具有复杂子查询的SQL查询

时间:2010-08-05 17:43:29

标签: sql sql-server sql-server-2000 subquery

我有两张桌子,Foo和Bar。 Foo包含Bar的主键(bar_id)的外键。 Bar的结构允许通过外键(bar_parent_id)与Bar中的另一个记录建立父/子关系。此关系是有限的,因此任何具有父级的条形记录本身不能是父级。但是,任何给定的父母都可以有多个孩子。

我的查询需要选择Foo中与Bar中给定记录匹配的所有记录以及任何Bar的父母,子女或兄弟姐妹。下面的查询有效,但有点慢。有没有办法构建它以便它运行得更快?

SELECT f.field1, f.field2
FROM Foo f
WHERE f.bar_id IN (
    SELECT bar_id 
    FROM Bar
    WHERE bar_id = @bar_id OR
    bar_parent_id = @bar_id OR 
    bar_id = (SELECT bar_parent_id FROM Bar WHERE bar_id = @bar_id) OR
    bar_parent_id = (SELECT bar_parent_id FROM Bar WHERE bar_id = @bar_id AND bar_parent_id > 0)
) 

P.S。这是真实查询的简化版本。它实际上与另一个表具有第二个相同的子查询,该表具有与Bar相同的自/父/子关系。

3 个答案:

答案 0 :(得分:2)

你可以尝试,但我不确定正确性

SELECT
    f.field1, f.field2 
FROM
    foo f 
    LEFT JOIN bar b
    LEFT JOIN bar bParent 
    ON b.parent_id = bParent.bar_id
    LEFT JOIN bar bChildren 
    ON b.bar_id = bChildren.Parent_id
WHERE
    b.bar_id = @bar_id
    or 
    bParent.bar_id = @bar_id
    or 
    bChildren.bar_id = @bar_id  

答案 1 :(得分:1)

试试这个:

SELECT f.field1, f.field2
  FROM Foo f
 WHERE EXISTS(SELECT NULL
                FROM BAR b
               WHERE b.bar_id = f.bar_id
                 AND (    @bar_id IN (b.bar_id, b.bar_parent_id)
                       OR EXISTS(SELECT NULL
                                   FROM BAR x
                                  WHERE x.bar_parent_id = b.bar_id
                                    AND x.bar_id = @bar_id)
                       OR EXISTS(SELECT NULL
                                   FROM BAR y
                                  WHERE y.bar_parent_id = b.bar_parent_id
                                    AND y.bar_id = @bar_id
                                    AND y.bar_parent_id > 0))

答案 2 :(得分:0)

OR经常会减慢SQL查询的速度。 可能执行得更好的另一种方法是将单独查询的结果合并,如下所示:

SELECT f.field1, f.field2 FROM Foo f where f.bar_id = @bar_id
UNION
SELECT f.field1, f.field2 FROM Foo f 
JOIN Bar b on f.bar_id = b.bar_id and @bar_id = b.bar_parent_id
UNION
SELECT f.field1, f.field2 FROM Foo f 
JOIN Bar bsib on f.bar_id = bsib.bar_id 
JOIN Bar b on bsib.bar_parent_id = b.bar_parent_id and @bar_id = b.bar_id
UNION
SELECT f.field1, f.field2 FROM Foo f 
JOIN Bar bpar on bpar.bar_id = f.bar_id 
JOIN Bar b on bpar.bar_id = b.bar_parent_id and @bar_id = b.bar_id