MySQL 使用 GROUP_CONCAT 和多个 JOINS

Posted

技术标签:

【中文标题】MySQL 使用 GROUP_CONCAT 和多个 JOINS【英文标题】:MySQL Use GROUP_CONCAT with Multiple JOINS 【发布时间】:2015-04-05 11:39:40 【问题描述】:

我有以下四个表。我的查询正常工作,但我需要让字段“AUTHORIZED_VIEWER”和“AUTHORIZED_VIEWER_EMAIL”返回所有值,而不仅仅是第一个值。我相信这可以通过使用 GROUP_CONCAT 来完成,但是,我不确定这部分应该如何实现。 注意 - 在尝试使用 GROUP_CONCAT 时,我必须使用以下语法,因为它返回一个 BLOB:

CONVERT(GROUP_CONCAT(authorized_viewer) USING utf8)

这是四个表:

users_tbl
+-----+------------------+
|id   |email             |  
+-----+------------------+
|10   | scott@co.com     |
|8    | cesar@co.com     |
|11   | kevin@co.com     |
|12   | jake@co.com      |
+-----+------------------+

authorized_viewers_tbl (authorized_viewer linked to id in users_tbl)
+-----+------------+------------------+
|id   |lightbox_id |authorized_viewer |   
+-----+------------+------------------+
|1    | 50         |11                |
|7    | 50         |8                 |
|3    | 31         |11                |
|5    | 30         |8                 |
|6    | 30         |11                |
|8    | 16         |11                |
|9    | 16         |10                |
|10   | 5          |10                |
|11   | 5          |11                |
+-----+------------+------------------+

lightboxes_tbl
+-----+------------------+---------------+
|id   |lightbox_name     |author         |   
+-----+------------------+---------------+
|5    | Test Lightbox #1 |jake@co.com    |
|16   | Test Lightbox #2 |cesar@co.com   |
|30   | Test Lightbox #3 |scott@co.com   |
|31   | Test Lightbox #4 |kevin@co.com   |
|50   | Test Lightbox #5 |cesar@co.com   |
+-----+------------------+---------------+

lightbox_assets_tbl
+-------+-------------+------------------+------------------=---+----------+
|id     |lightbox_id  |asset_name        |asset_path            | asset_id |
+-------+-------------+------------------+----------------------+----------+
|232    |30           |b757.jpg          |SWFs/b757.jpg         | 3810     |
|230    |31           |b757.jpg          |SWFs/b757.jpg         | 3810     |
|233    |16           |a321_takeoff.jpg  |SWFs/a321_takeoff.jpg | 3809     |
|234    |31           |a321_takeoff.jpg  |SWFs/a321_takeoff.jpg | 3809     |
|235    |50           |a330_landing.png  |SWFs/a330_landing.png | 3789     |
+-------+-------------+------------------+-----------------------+---------+

这是我当前使用的查询:

SELECT lb.id,
   lb.lightbox_name,
   lb.author,
   avt.authorized_viewer,
   u.email AS authorized_viewer_email,
   COUNT(lba.lightbox_id) total_assets
FROM lightboxes_tbl lb
LEFT JOIN lightbox_assets_tbl lba ON lb.id = lba.lightbox_id
LEFT JOIN authorized_viewers_tbl avt ON avt.lightbox_id = lb.id
LEFT JOIN users_tbl u ON u.id = avt.authorized_viewer
WHERE lb.author = 'scott@co.com'
  OR avt.authorized_viewer =
    (SELECT id
     FROM users_tbl
     WHERE email = 'scott@co.com')
GROUP BY lb.id
ORDER BY lb.lightbox_name ASC

SQL Fiddle

谢谢!

[编辑] 基于 SQL Fiddle 的预期结果:

 +-------+----------------+--------------+-------------------+--------------------------+--------------+
 |id     |lightbox_name   |author        |authorized_viewer  | email                    | total_assets |
 +-------+----------------+--------------+-------------------+--------------------------+--------------+
 |5      |Test Lightbox#1 |jake@co.com   |10,11              |scott@co.com,kevin@co.com |0             |             
 |16     |Test Lightbox#2 |cesar@co.com  |10,11              |scott@co.com,kevin@co.com |1             |
 |30     |Test Lightbox#3 |scott@co.com  |11,8               |kevin@co.com,cesar@co.com |1             |
 +-------+-------------+-----------------+-------------------+--------------------------+--------------+

【问题讨论】:

@xQbert 非常接近。对于“scott@co.com”不是作者而是authorized_viewer 的行,它只列出scott@co.com。如果可能的话,我需要它列出所有authorized_viewers,其中scott@co.com 是其中之一。那有意义吗?谢谢! 是的,我认为您的第一次尝试更接近。所以我期望的是,任何以“scott@co.com”为作者的灯箱都会被退回,包括所有授权查看者(以及列出的所有其他信息——这似乎是正确的)。此外,“scott@co.com”是authorized_viewer 的任何灯箱都将被退回,包括其他authorized_viewer。用户可以是作者或authorized_viewer,但不能同时是两者。希望这可以帮助。感谢您一直以来的帮助。 我看着这个小提琴,sqlfiddle.com/#!2/6f3d7/6/0,它列出了 lb #30 的两个资产 - 我不知道为什么。无论如何,我只是看了你更新的小提琴,我相信它是正确的!!!谢谢你的帮助。如果您想创建一个答案,我会将其标记为正确。 好的,我可以复制它。看看这个 SQL Fiddle -sqlfiddle.com/#!2/ccc6a/1,最后一行 - LB #31。 A & B 列有重复条目。 简单的方法是将 distinct 添加到 group by。 group_concat(distinct avt.authorized_viewer) a, group_concat(distinct u.email) b, sqlfiddle.com/#!2/ccc6a/2/0 需要不同的。这是由于我们需要它的 lightbox_assets_tbl 中的双重条目。 【参考方案1】:

有一种更简洁的方法可以做到这一点,但我还没有时间考虑它。

一个有趣的问题,感谢分享并希望我们提供帮助!

    我们将group_concat 添加到avt.authorized_vieweru.email 我们将distinct 添加到group_concat 以仅根据请求拉回唯一值。 我们为每个非聚合值添加了group by。 我们更改了 where 子句,将 Scott 作为审阅者的所有灯箱都拉入。通过使用作者字段作为限制,我们排除了其他审稿人。通过根据灯箱的Id进行过滤,我们保留所有用户;这允许 group_concat 按需要工作。

.

SELECT lb.id,
       lb.lightbox_name,
       lb.author,
       group_concat(distinct avt.authorized_viewer) a,
       group_concat(distinct u.email) b,
       COUNT(distinct lba.id) total_assets
FROM lightboxes_tbl lb
LEFT JOIN lightbox_assets_tbl lba ON lb.id = lba.lightbox_id
LEFT JOIN authorized_viewers_tbl avt ON avt.lightbox_id = lb.id
LEFT JOIN users_tbl u ON u.id = avt.authorized_viewer
where lb.author = 'scott@co.com'
or 
lb.id in (Select lightbox_ID 
          from authorized_Viewers_tbl X
          INNER JOIN users_Tbl U on U.ID = X.authorized_Viewer
          WHERE email = 'scott@co.com')
GROUP BY lb.id, lb.lightbox_name, lb.author
ORDER BY lb.lightbox_name ASC

http://sqlfiddle.com/#!2/ccc6a/2/0 希望这可以为您解决问题! (从基本主题中清除了几个 cmets,因为我现在已将它们包含在内或此处收集的信息。)

【讨论】:

我绝对不是 SQL 专家,所以如果有更简洁的方法来编写这个并且你有时间去做,我很乐意看到它。再次感谢!!!【参考方案2】:

试试这个:-

SELECT lb.id,
   lb.lightbox_name,
   lb.author,
   avt.authorized_viewer,
   u.email AS authorized_viewer_email,
   COUNT(lba.lightbox_id) total_assets
FROM lightboxes_tbl lb
LEFT JOIN lightbox_assets_tbl lba ON lb.id = lba.lightbox_id
LEFT JOIN authorized_viewers_tbl avt ON avt.lightbox_id = lb.id
LEFT JOIN users_tbl u ON u.id = avt.authorized_viewer
WHERE lb.author = 'scott@co.com'
OR avt.authorized_viewer =
(SELECT id
 FROM users_tbl
 WHERE email = 'scott@co.com')
GROUP BY lb.id, lb.lightbox_name, lb.author, avt.authorized_viewer, u.email
ORDER BY lb.lightbox_name

【讨论】:

以上是关于MySQL 使用 GROUP_CONCAT 和多个 JOINS的主要内容,如果未能解决你的问题,请参考以下文章

MySQL SELECT 从多个表,多个 GROUP BY 和 group_concat?

多个表上的mysql group_concat

MySQL - GROUP_CONCAT 返回重复数据,不能使用 DISTINCT

在 MySQL 中具有多个连接的 group_concat

mysql中concat 和 group_concat()的用法

mysql中concat 和 group_concat()的用法