【发布时间】:2011-01-30 23:24:37
【问题描述】:
我经常发现自己在一张桌子上执行几个独立连接。例如,假设我们有表collections,它与photos 和songs 具有独立的一对N 关系,其中N 是从零到多。
现在,假设我们想要获得一个集合,以及它(独立)相关的照片和歌曲。
我通常会使用这样的东西:
SELECT
collections.collectionid as collectionid,
photos.name as photo_name,
songs.name as song_name
FROM collections
LEFT JOIN photos ON collections.collectionid = photos.collectionid
LEFT JOIN songs ON collections.collectionid = songs.collectionid
WHERE collections.collectionid = 14
当然,将一个表左连接到另外两个表,如果第一个连接产生M 行,第二个连接产生N 行,则给出M * N 行。就数据库流量和性能而言,这似乎不是最理想的。
+--------------+------------+-----------+
| collectionid | photo_name | song_name |
+--------------+------------+-----------+
| 14 | 'x' | 'a' | \
| 14 | 'x' | 'b' | - Each photo is returned 3 times,
| 14 | 'x' | 'c' | / because 3 songs are returned.
| 14 | 'y' | 'a' | \
| 14 | 'y' | 'b' |
| 14 | 'y' | 'c' | /
+--------------+------------+-----------+
或者,您可以执行两个选择:两个单独的查询,每个查询将 collections 连接到不同的表,提供 M + N 行:
SELECT
collections.collectionid as collectionid
song.name as song_name
FROM collections
LEFT JOIN songs on collections.collectionid = songs.collectionid
WHERE collections.collectionid = 14
和:
SELECT
collections.collectionid as collectionid
photos.name as photo_name
FROM collections
LEFT JOIN photos on collections.collectionid = photos.collectionid
WHERE collections.collectionid = 14
给予:
+--------------+------------+ +--------------+------------+
| collectionid | song_name | | collectionid | photo_name |
+--------------+------------+ +--------------+------------+
| 14 | 'a' | | 14 | 'x' |
| 14 | 'b' | | 14 | 'y' |
| 14 | 'c' | +--------------+------------+
+--------------+------------+
我的问题:处理这个问题的最佳方法是什么?
以上都不是最优的。那么,是否有另一种方法可以生成 M + N 行,但可以在单个查询中完成?
【问题讨论】:
-
在 MySQL 中,您可以使用
group_concat每组返回 1 行。不知道性能影响。 -
谢谢马丁。哇,时髦。据我所知,它在生成后聚合了结果——因此不会改变查询本身的“M*”性能问题。然而,由于它减少了行数,它应该减少循环的长度,在 PHP 中,调用
mysql_fetch_assoc。 -
这就是连接在 SQL 中的工作方式,如果不需要此结果,您几乎需要 2 个查询。
-
你喜欢什么样的输出?您是否正在为每个匹配对象寻找一排,即两排照片和三排歌曲?