2010-08-05 56 views
3

我有兩個表,Foo和Bar。 Foo包含Bar的主鍵(bar_id)的外鍵。 Bar的結構允許父/子關係通過外鍵(bar_parent_id)與Bar中的另一條記錄進行關聯。這種關係是有限的,任何具有父母的條形記錄本身都不能成爲父母。但是,任何給定的父母可以有多個孩子。帶有複雜子查詢的SQL查詢

我的查詢需要選擇Foo中與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具有相同自/父/子關係的表具有相同的子查詢。

+0

您是否嘗試過使用exists代替爲您的WHERE子句? – JNK 2010-08-05 17:52:56

回答

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)) 
+0

+ 1 for @bar_id IN(b.bar_id,b.bar_parent_id)。我從來沒有想到這個 – 2010-08-05 17:58:46

+0

真棒查詢!我不知道IN語法是可能的。可悲的是,這仍然比我原來的查詢慢一點。 – 2010-08-05 20:58:34

+0

@NorwegianWood:這是因爲OR – 2010-08-05 21:00:35

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 
+0

你會想DISTINCT - 加入風險複製記錄。 – 2010-08-05 18:00:15

+0

第一次連接需要一個ON子句。無論如何,這個比我現有的要慢很多。 – 2010-08-05 20:59:15

0

手術室經常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