2012-06-12 61 views
0

我有這些表加入查詢與多個標準

places(place_id, place_name) 
places_criteria(place_id, criterion_id) 
criteria(criterion_id, criterion_name) 

「places_criteria」有外鍵到「地方」和「標準」。我可以通過一個標準獲得很多地方。

SELECT p.place_id, p.place_name 
FROM places p INNER JOIN places_criteria pc ON p.place_id = pc.place_id 
WHERE pc.criterion_id = <some_id> 

如何通過多個標準獲取多個地點?

例如:迪斯尼樂園是一個地方(place_id = 1),它是 「良好」(criterion_id = 1)和 「有趣」(criterion_id = 2)。

places_criteria的數據:

place_id criterion_id 
1   1 
1   2 

現在,我想這是「好」和「有趣」的地方。

+1

我認爲您對問題的描述不夠清晰。你能舉出這些表格中的數據的例子,以及你想要的結果的例子嗎? – GolezTrol

回答

3

硬編碼版本是爲了加入你自己所需的每個標準...

SELECT 
    c1.place_id 
FROM 
    places_criteria  AS c1 
INNER JOIN 
    places_criteria  AS c2 
    ON c2.place_id = c1.place_id 
WHERE 
     c1.criterion_id = 1 
    AND c2.criterion_id = 2 

這很有效,但如果要查詢一個動態數量的criterion_ids,則需要動態SQL。

另一種方法是使用IN (1,2)(或加盟等,以執行類似的功能)得到答案Places with criterion 1 <OR> 2,然後使用HAVING子句只包括兩種不同標準的地方。

SELECT 
    place_id 
FROM 
    places_criteria 
WHERE 
    criterion_id IN (1,2) 
GROUP BY 
    place_id 
HAVING 
    COUNT(DISTINCT criterion_id) = 2 
2

你可以這樣做:

SELECT p.place_id, p.place_name 
FROM places p, places_criteria pc1, places_criteria pc2, places_criteria pc3 
WHERE p.place_id = pc2.place_id and pc1.criterion_id = <some_id> 
and p.place_id = pc2.place_id and pc2.criterion_id = <some_id> 
and p.place_id = pc3.place_id and pc3.criterion_id = <some_id> 

但是我有其他關於你的問題的理解一個疑問:爲什麼你向我們展示criteria表?

+0

當您需要多個條件時,這不會允許查詢的輕鬆增長,因此此解決方案過於複雜且非常不靈活。 – GolezTrol

+2

像這樣的查詢是建立在一個程序中的,它提供了輸入多個標準的能力。這就是爲什麼這是通用的方式。 –

1

使用in從一組中進行選擇。您可以使用子選擇來獲得正確的位置ID,或者您可以像我一樣使用distinct,這在MySQL中可能會更快。

select distinct 
    p.place_id, 
    p.place 
from 
    places p 
    inner join places_criteria pc on pc.place_id = p.place_id 
    inner join criteria c on c.criterion_id = pc.criterion_id 
where 
    /* Either by name */ 
    c.criterion_name in ('crit A', 'crit B', 'crit C') 
    /* Or by id */ 
    OR c.criterion_id in (1, 2, 3, 4, 5) 

解決方案2.匹配所有條件。通過檢查計數來做到這一點。

select 
    p.place_id, 
    p.place 
from 
    places p 
    inner join places_criteria pc on pc.place_id = p.place_id 
    inner join criteria c on c.criterion_id = pc.criterion_id 
where 
    c.criterion_name in ('crit A', 'crit B', 'crit C') 
group by 
    p.place_id, 
    p.place 
having 
    count(*) = 3 /* the number of criteria */ 
+1

嗨,但「IN」表示「OR」狀態。我想要獲得所有「好」和「有趣」的地方。你能否給出其他答案? – Emerald214

+0

如你所願。請參閱編輯。你仍然有一些靈活性。您只需指定一個條件列表和您指定的條件數量,而無需添加其他連接。 – GolezTrol

1

如果你想滿足以下任一個條件的所有地方:如果要滿足所有的幾個標準的所有地方

SELECT p.place_id, p.place_name 
FROM places p 
INNER JOIN places_criteria pc ON p.place_id = pc.place_id 
WHERE pc.criterion_id = <some_id> 
OR pc.criterion_id = <some_id2> 
OR pc.criterion_id = <some_id3> 
GROUP BY p.place_id, p.place_name 

SELECT p.place_id, p.place_name 
FROM places p 
INNER JOIN places_criteria pc1 ON p.place_id = pc1.place_id 
INNER JOIN places_criteria pc2 ON p.place_id = pc2.place_id 
INNER JOIN places_criteria pc3 ON p.place_id = pc3.place_id 
WHERE pc1.criterion_id = <some_id> 
AND pc2.criterion_id = <some_id2> 
AND pc3.criterion_id = <some_id3> 
+0

後者適合我的需求,但表現如何? – Emerald214

+0

@ Emerald214據我所知,這是做這種搜索的最佳方式。也許別人知道更快的方法。 – Pablo