在 postgreSQL 中使用 WHERE 子句创建三个表的最有效方法是啥
Posted
技术标签:
【中文标题】在 postgreSQL 中使用 WHERE 子句创建三个表的最有效方法是啥【英文标题】:What the most efficient way to make a three tables JOIN with a WHERE clause in postgreSQL在 postgreSQL 中使用 WHERE 子句创建三个表的最有效方法是什么 【发布时间】:2015-04-04 11:04:54 【问题描述】:我正在使用 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');
我想知道是否有更有效的方法来做到这一点?
【问题讨论】:
看起来您的查询不正确,您正在将 aG.artitsId 与genres.genreId 进行匹配。 你说得对,我编辑了我的问题。 一个艺术家可以有多个流派吗? (例如,artistgenres 行是否存在 artistId=1,genreId=2 ?) @wildplasser ,是的,它可以拥有。 【参考方案1】:如果可以通过连接完成,一般最好不要使用子查询。然而幸运的是,查询规划器会为您重写子查询作为连接!如果你自己做的话,它会是这样的。
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 会将它们重新排序为它认为最有效的顺序。
【讨论】:
【参考方案2】: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'
);
【讨论】:
感谢您的回答,但是您的查询似乎比Eelke的查询慢了一点(但是我的测试表很小,可能是这个原因)。 对于非平凡的情况,它只能更快。请注意,查询将产生不同的结果:在每个艺术家不止一个流派的情况下(这也需要选择以允许多个选择,例如在AND g.name IN( 'country', 'dub')
中,@Eelke 的查询将为每个艺术家产生多个结果行,为每位艺术家挖掘一(或零)行。
考虑添加几行简短的解释,说明为什么这是最好的(以及在什么情况下)。指向良好参考的链接也会有所帮助。
@wildplasser:Eelke 的查询如何为每个艺术家生成多个结果行(因为一个艺术家可以有多个流派但不能有多个相同流派)?以上是关于在 postgreSQL 中使用 WHERE 子句创建三个表的最有效方法是啥的主要内容,如果未能解决你的问题,请参考以下文章
postgresql 在 where 子句中使用 json 子元素