Sql 使用 ;单独询问?

Sql 使用 ;单独询问?,sql,mysql,join,Sql,Mysql,Join,我经常发现自己在一张桌子上进行几次独立的连接。例如,假设我们有一个表collections,它与照片和歌曲都有独立的一对N关系,其中N是从零到多 现在,假设我们想要一个收藏,以及它(独立)关联的照片和歌曲 我通常会使用以下内容: SELECT collections.collectionid as collectionid, photos.name as photo_name, songs.name as song_name FROM collections

我经常发现自己在一张桌子上进行几次独立的连接。例如,假设我们有一个表
collections
,它与
照片
歌曲
都有独立的一对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
以及:

给予:

+--------------+------------+    +--------------+------------+
| collectionid | song_name  |    | collectionid | photo_name |
+--------------+------------+    +--------------+------------+
| 14           | 'a'        |    | 14           | 'x'        |
| 14           | 'b'        |    | 14           | 'y'        |
| 14           | 'c'        |    +--------------+------------+
+--------------+------------+
我的问题是:处理这个问题的最佳方式是什么


以上两种都不理想。那么,是否有另一种方法可以产生
M+N
行,但可以在单个查询中完成?

照片和权限之间的关系似乎没有定义,这导致了您所说的交叉连接。是的,从表面上看,做两个查询比你现有的要好。然而,真正的问题是为什么照片和权限没有基于密钥的关系

但也许我不理解你的整体模式。也许所有的权限都属于一个用户。如果是,那么我会考虑将所有权限放在一行(几列或一个XML块)上,而不是在几行中。这样做将允许单个查询获取所有值,而不会导致无意的交叉联接。

您的第一个选项(两个独立联接)似乎没有为您提供非常有用的结果集(因为这两个附属表生成半笛卡尔积,您必须在应用程序代码中消除重复结果)

第二个选项(两个单独的查询)是可以的,除非您希望将两个查询的结果作为一个集合来进行表示(例如,按日期字段将它们全部排序)

我认为,最好的解决方案是将两个查询与
UNION ALL
组合成一个查询,生成一个只包含实际需要的行的结果集:

SELECT
  collections.collectionid as collectionid,
  photos.name as photo_name,
  'photo' as document_type
FROM collections
  LEFT JOIN photos on collections.collectionid = photos.collectionid
WHERE collections.collectionid = 14
UNION ALL
SELECT
  collections.collectionid as collectionid,
  song.name as photo_name
  'song' as document_type
FROM collections
  LEFT JOIN songs on collections.collectionid = songs.collectionid
WHERE collections.collectionid = 14

这种结果集可以按整个组合记录集中的任何字段排序,例如要获取附加到集合的20个最新文档,无论它们是什么类型。

在MySQL中,您可以使用
group\u concat
为每个组返回1行。不知道性能影响。感谢Martin。哇,funky。据我所知,这会在生成后聚合结果,因此不会更改“M*”查询本身的性能问题。然而,由于它减少了行数,它应该减少循环的长度,在PHP中,比如调用
mysql\u fetch\u assoc
。这就是连接在SQL中的工作方式,如果不需要这个结果,您几乎需要两个查询。您希望哪种输出?您是否希望每ma一行对象,所以两个照片行和三个歌曲行?权限应用于收藏,而不是照片。照片和权限之间没有关系。
权限
有列
收藏ID
用户ID
,和
权限
。重点是我们正在对
收藏进行两个独立的连接
表,使用它的主键:一个到
照片
,一个到
权限
。问题是是否最好将它们分开,或者以不同的方式执行它们。@Benji:由于权限和照片之间没有关系,那么应该进行两个单独的查询。您是否可以对此进行扩展?例如,您的推理是基于性能、清晰性还是RDBMS的纯度?非常感谢。由于它只需要比两个单独的查询多做一些工作,但将它们结合在一起,因此它的性能似乎也比Q中给出的任何一个选项都要好。
SELECT
  collections.collectionid as collectionid,
  photos.name as photo_name,
  'photo' as document_type
FROM collections
  LEFT JOIN photos on collections.collectionid = photos.collectionid
WHERE collections.collectionid = 14
UNION ALL
SELECT
  collections.collectionid as collectionid,
  song.name as photo_name
  'song' as document_type
FROM collections
  LEFT JOIN songs on collections.collectionid = songs.collectionid
WHERE collections.collectionid = 14