50

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

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

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

这样,我可以通过稍后在我的代码中将 idlist 拆分为 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 要求的行。

4

5 回答 5

121

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

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

于 2012-03-25T08:30:53.317 回答
14

您不能在此类查询中访问外部范围内的变量(不能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;

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

于 2008-12-18T13:50:54.330 回答
2

我认为您可能有“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
于 2008-12-19T02:36:40.010 回答
1

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
于 2008-12-18T14:01:48.927 回答
1

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

  • 主表:会话(演示会话)(uid,名称,..)
  • 第一个子表:带有 key session_id (uid, session_uid, date, time_start, time_end) 的事件
  • 第二个子表:accessories_needed(笔记本电脑、投影仪、麦克风等),键为 session_id(uid、session_uid、accessory_name)
  • 第三个子表:session_presenters(演示者),key为session_id(uid,session_uid,presenter_name,address...)

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

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

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>" 在查询中用作分隔符将列表项中的结果分开。

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

于 2011-12-15T14:38:09.497 回答