2012-06-20 79 views
2

假設我們有兩個表Foo和Bar。對於Foos和Bars之間的多對多關係,我有一個關聯表Foo_Bar。查詢中的SQL動態

現在我基本上想要一個查詢來選擇匹配動態條數限制的Foos。我可以動態生成與加入適當數量的查詢做到這一點:

SELECT * 
FROM Foo F INNER JOIN 
    Foo_Bar FB1 ON FB1.FooId = F.Id AND FB1.BarId= Y INNER JOIN 
    Foo_Bar FB2 ON FB2.FooId = F.Id AND FB2.BarId= Z INNER JOIN 
    --one inner join for each constraint 

我想知道是否有更簡單的方法。我基本上要像這樣的查詢:

SELECT * 
FROM Foo F 
WHERE (Y, Z, ...) IN (SELECT BarId FROM Foo_Bar WHERE FooId = F.Id) 

當然,這不是有效的SQL,但我想知道如果動態查詢是爲了達到預期的效果的唯一合理的可移植的方法。

+1

你可以做'JOIN foo_bar這樣FB1 ON FB1.FooId = F.Id WHERE FB1.BarId IN(Y,Z, ....)' – Lamak

+0

不完全。見下面我對Dancrumb的回覆。 – naasking

回答

1

我假設你想要一個關係部門查詢。看到這個問題有很多方法可以做到這一點:How to filter SQL results in a has-many-through relation

也有@歐文的回答(爲Postrgres)性能測試,你會發現,動態的方式(使用很多連接或許多EXISTS子查詢或許多IN子查詢)比僅使用變量表或列表的靜態查詢執行得更快。

在您的服務器上進行測試,並確認您的數據。 MySQL例如在IN子查詢中存在一些性能問題,所以我期望它在JOIN版本中執行得更快。

這裏的「歐文1」查詢,翻譯成你的表:

SELECT f.* 
FROM Foo f 
JOIN (
    SELECT FooId 
    FROM Foo_Bar 
    WHERE BarId IN (Y, Z, ...)    --- your list or table here 
    GROUP BY FooId 
    HAVING COUNT(*) = @N      --- the size of this list or table 
    ) fb ON fb.FooId = f.Id; 
+0

您鏈接到的令人感興趣的線索。我確信必須有一種方法來使用簡單的參數而不是動態sql來編寫這種查詢,我認爲你已經很好地回答了這個挑戰,所以謝謝! – naasking

1

此基礎上你給的信息,下面的查詢會得到你需要的數據:

SELECT * 
FROM Foo F INNER JOIN 
    Foo_Bar FB ON FB1.FooId = F.Id 
WHERE FB.BarId IN (Y, Z, ...) 
+0

您的建議匹配FB.BarId爲Z或Y的所有記錄或...我希望F的所有記錄都有FB.BarId爲Z和Y AND ...基本上是您提供的查詢的對偶。 – naasking