我正在使用postgreSQL 9.3。
我想说我的问题有点主观,但我没有找到任何相关的问题或文章。。。
我有三张表如下:
艺术家:
+--------+----------+
|artistId| name |
+--------+----------+
| 1 | James |
| 2 | Jack |
| 3 | Henry |
| 4 | Tom |
+--------+----------+
流派:
+---------+-----------+
| genreId | name |
+---------+-----------+
| 1 | rock |
| 2 | dub |
+---------+-----------+
和交叉表艺术家流派:
+--------+---------+
|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');
我想知道是否有更有效的方法?
通常,如果可以使用联接来完成子查询,则最好不要使用子查询。不过,如果运气好的话,查询规划器会为您重写子查询作为联接!以下是如果你自己做的话会是什么样子。
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会将它们重新排序为它认为最有效的顺序。
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'
);