2015-04-04 49 views
1

我正在使用postgreSQL 9.3。什麼是最有效的方法來創建一個三表在JOG與PostgreSQL中的WHERE子句

我想說,我的問題是有點主觀的,但我沒有找到任何相關的問題或文章...

我有三個表如下:

藝術家:

+--------+----------+ 
|artistId| name | 
+--------+----------+ 
| 1  | James | 
| 2  | Jack  | 
| 3  | Henry | 
| 4  | Tom  | 
+--------+----------+ 

類型:

+---------+-----------+ 
| genreId | name | 
+---------+-----------+ 
| 1  | rock | 
| 2  | dub  | 
+---------+-----------+ 

和接線表artistsGenres:

+--------+---------+ 
|artistId| genreId | 
+--------+---------+ 
|  1 |  1 | 
|  2 |  2 | 
|  3 |  1 | 
|  4 |  2 | 
+--------+---------+ 

我想通過流派的名字得到所有的藝術家。 因爲我不喜歡這樣的時刻:

SELECT a.* 
FROM artistsGenres aG 
    INNER JOIN artists a ON a.artistId = aG.artistId 
WHERE aG.genreId = (SELECT genreId FROM genres WHERE name = 'dub'); 

我不知道是否有更有效的方式來做到這一點?

+0

看起來你的查詢不正確,你對照genres.genreId匹配aG.artitsId。 – Eelke 2015-04-04 11:26:56

+0

你是對的,我編輯了我的問題。 – Simon 2015-04-04 11:33:06

+0

一位藝術家可以擁有多種流派嗎? (例如,藝術家行可以存在與{artistId = 1,genreId = 2}?) – wildplasser 2015-04-04 11:51:56

回答

2

一般情況下,最好不要使用子查詢,如果可以通過連接完成。然而,如果運氣好一點的話,查詢規劃器會將子查詢重寫爲您的聯接!如果你自己做了,看看它會是怎樣。

SELECT a.* 
FROM artistsGenres aG 
    INNER JOIN artists a ON a.artistId = aG.artistId 
    INNER JOIN genres g ON g.genreId=aG.genreId 
WHERE g.name='dub' 

以何種順序進行連接並不重要,因爲postgresql會將它們重新排序,使其達到最佳效果。

1
SELECT * 
FROM artists a 
WHERE EXISTS (
    SELECT 1 
    FROM artistsGenres aG 
    JOIN genres g ON g.genreId = aG.genreId 
    WHERE aG.artistId = a.artistId 
    AND g.name = 'dub' 
); 
+0

感謝您的回答,但您的查詢似乎比Eelke的查詢慢一點(但我的測試表非常小,這也許是原因)。 – Simon 2015-04-04 13:53:39

+0

對於非平凡的情況,它只能更快。請注意,查詢會產生不同的結果:對於每位藝術家多於一種流派的情況(這也需要選擇以允許多種選擇,如'AND g.name IN('country','dub' ),@埃爾克的查詢將產生每個藝術家多個結果行,每個藝術家排除一行(或零)。 – wildplasser 2015-04-04 14:55:19

+0

考慮添加一些簡短的解釋行,爲什麼這是最好的(以及在什麼情況下)。 – TheCodeArtist 2015-04-05 04:06:38

相關問題