繁体   English   中英

在MySQL中的子查询上使用GROUP_CONCAT

[英]Using GROUP_CONCAT on subquery in MySQL

我有一个MySQL查询,我想在其中包含另一个表中的ID列表。 在网站上,人们可以添加某些项目,然后人们可以将这些项目添加到他们的收藏夹中。 我基本上想要获得那些喜欢该项目的人的ID列表(这有点简化,但这就是它归结为)。

基本上,我做这样的事情:

SELECT *,
GROUP_CONCAT((SELECT userid FROM favourites WHERE itemid = items.id) SEPARATOR ',') AS idlist
FROM items
WHERE id = $someid

通过这种方式,我可以通过在我的代码中进一步将id列表转换为PHP中的数组来显示谁喜欢某个项目,但是我收到以下MySQL错误:

1242 - 子查询返回超过1行

我认为这有点使用GROUP_CONCAT而不是例如CONCAT 我是以错误的方式来做这件事的吗?


好的,感谢到目前为止的答案,这似乎有效。 然而,有一个问题。 如果该项目由该用户添加,则该项目也被视为最受欢迎。 所以我需要额外的检查以检查creator = userid。 有人可以帮我提出一个聪明(并希望有效)的方法吗?

谢谢!

编辑:我只是试图这样做:

SELECT [...] LEFT JOIN favourites ON (userid = itemid OR creator = userid)

idlist是空的。 请注意,如果我使用INNER JOIN而不是LEFT JOIN我会得到一个空结果。 即使我确信有些行符合ON要求。

OP几乎是正确的。 GROUP_CONCAT应该包装子查询中的列而不是完整的子查询 (我正在解雇分隔符,因为逗号是默认值):

SELECT i.*,
(SELECT GROUP_CONCAT(userid) FROM favourites f WHERE f.itemid = i.id) AS idlist
FROM items i
WHERE i.id = $someid

这将产生所需的结果,也意味着接受的答案部分错误,因为您可以访问子查询中的外部范围变量。

您无法在此类查询中访问外部作用域中的变量(不能使用items.id )。 你应该尝试类似的东西

SELECT
    items.name,
    items.color,
    CONCAT(favourites.userid) as idlist
FROM
    items
INNER JOIN favourites ON items.id = favourites.itemid
WHERE
    items.id = $someid
GROUP BY
    items.name,
    items.color;

根据需要展开字段列表(名称,颜色......)。

我认为你可能有“userid = itemid”错误,不应该是这样的:

SELECT ITEMS.id,GROUP_CONCAT(FAVOURITES.UserId) AS IdList
FROM FAVOURITES 
INNER JOIN ITEMS ON (ITEMS.Id = FAVOURITES.ItemId OR FAVOURITES.UserId = ITEMS.Creator)
WHERE ITEMS.Id = $someid
GROUP BY ITEMS.ID

GROUP_CONCAT的目的是正确的,但子查询是不必要的,并导致问题。 试试这个:

SELECT ITEMS.id,GROUP_CONCAT(FAVOURITES.UserId)
FROM FAVOURITES INNER JOIN ITEMS ON ITEMS.Id = FAVOURITES.ItemId
WHERE ITEMS.Id = $someid
GROUP BY ITEMS.ID

是的,soulmerge的解决方案还可以。 但我需要一个查询,我必须从更多的子表中收集数据,例如:

  • 主表: 会话 (演示会话)(uid,name,..)
  • 第一个子表:具有关键session_id的事件 (uid,session_uid,date,time_start,time_end)
  • 第二个子表: accessories_needed (笔记本电脑,投影仪,麦克风等),带有密钥session_id(uid,session_uid,accessory_name)
  • 第3个子表:具有密钥session_id的session_presenters (演示者人员)(uid,session_uid,presenter_name,地址...)

每个会话在子表表中有更多行(更多时间表,更多附件)

我需要在每个会话中收集一个集合以显示在矿石行(其中一些):

session_id | session_name | date | time_start | time_end | accessories | presenters

我的解决方案(经过几个小时的实验):

SELECT sessions.uid, sessions.name,
    ,(SELECT GROUP_CONCAT( `events`.date SEPARATOR '</li><li>') 
            FROM `events` 
            WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS date
    ,(SELECT GROUP_CONCAT( `events`.time_start SEPARATOR '</li><li>') 
            FROM `events` 
            WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS time_start
    ,(SELECT GROUP_CONCAT( `events`.time_end SEPARATOR '</li><li>') 
            FROM `events` 
            WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS time_end
    ,(SELECT GROUP_CONCAT( accessories.name SEPARATOR '</li><li>') 
            FROM accessories 
            WHERE accessories.session_id = sessions.uid ORDER BY accessories.name) AS accessories
    ,(SELECT GROUP_CONCAT( presenters.name SEPARATOR '</li><li>') 
            FROM presenters
            WHERE presenters.session_id = sessions.uid ORDER BY presenters.name) AS presenters

    FROM sessions

所以不需要JOIN或GROUP BY。 显示数据友好的另一个有用的东西(当“回显”它们时):

  • 你可以将events.date,time_start,time_end等包装在“<UL> <LI> ... </ LI> </ UL>”中,这样​​“<LI> </ LI>”在查询中用作分隔符将列表项中的结果分开。

我希望这可以帮助别人。 干杯!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM