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_viewer
和u.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 返回重复数据,不能使用 DISTINCT