MySQL嵌套选择多列

时间:2013-03-22 20:45:48

标签: mysql subquery

我目前正在尝试检索最新帖子及其相关帖子(每个帖子的x号码)。我手头有以下查询:

SELECT id, title, content
       (SELECT GROUP_CONCAT(title) FROM posts        -- Select title of related posts 
        WHERE id <> p.id AND id IN (                 
           SELECT p_id FROM tagsmap                  -- Select reletad post ids from tagsmap
           WHERE t_id IN (
              SELECT t_id FROM tagsmap               -- Select the tags of the current post 
              WHERE p_id = p.id) 
           ) ORDER BY id DESC LIMIT 0, 3) as related 
FROM posts as p ORDER BY id DESC LIMIT 5

我的数据库结构很简单:一个帖子表。标签表。还有一个tagsmap表,我将帖子与标签相关联。

这个查询工作正常(虽然我不知道它的性能,因为表中没有很多行 - 也许解释可以帮助我,但现在情况并非如此)。

我真正需要的是检索相关帖子的ID及其标题。

所以我想做SELECT GROUP_CONCAT(title), GROUP_CONCAT(id),但我知道会导致错误。那么在这种情况下,检索id和标题的最佳方法是什么?我不想重写整个子查询只是检索id。应该有另一种方式。

修改

SELECT p1.id, p1.title, p1.content,
    group_concat(DISTINCT p2.id) as 'P IDs',
    group_concat(DISTINCT p2.title) as 'P titles'
FROM posts as p1
LEFT JOIN tagsmap as tm1 on tm1.p_id = p1.id
LEFT JOIN tagsmap as tm2 on tm2.t_id = tm1.t_id and tm1.p_id <> tm2.p_id
LEFT JOIN posts as p2 on p2.id = tm2.p_id
GROUP BY p1.id
ORDER BY p1.id desc limit 5;

最后这是我用过的查询。我删除了Where子句,因为它没有必要并使用LEFT JOIN而不是JOIN,否则会忽略没有标记的帖子。最后将DISTINCT添加到group_concat中,因为它连接了重复的行(例如,如果帖子有多个带有相关帖子的常用标签,则会导致重复的连接)。

上面的查询完美无缺。谢谢大家。

2 个答案:

答案 0 :(得分:2)

像这样?

SELECT id, title, content
       (SELECT GROUP_CONCAT(concat(cast(id as varchar(10)), ':', title)) FROM posts        -- Select title of related posts 
        WHERE id <> p.id AND id IN (                 
           SELECT p_id FROM tagsmap                  -- Select reletad post ids from tagsmap
           WHERE t_id IN (
              SELECT t_id FROM tagsmap               -- Select the tags of the current post 
              WHERE post_id = p.id) 
           ) ORDER BY id DESC LIMIT 0, 3) as related 
FROM posts as p ORDER BY id DESC LIMIT 5

答案 1 :(得分:2)

好的 - 这会有效,并且它具有消除子查询的额外优势(当你获得大量记录时可能会减慢你的速度):

SELECT p1.id, p1.title, p1.content,
    group_concat( p2.id) as 'P IDs',
    group_concat( p2.title) as 'P titles'
FROM posts as p1
JOIN tagsmap as tm1 on tm1.p_id = p1.id
JOIN tagsmap as tm2 on tm2.t_id = tm1.t_id and tm1.p_id <> tm2.p_id
JOIN posts as p2 on p2.id = tm2.p_id
WHERE p2.id <> p1.id
GROUP BY p1.id
ORDER BY p1.id desc limit 5;

我们在这里做的是从帖子的第一个版本中选择你想要的内容,通过post.id将它们连接到tagsmap,按标签id自行连接到tagsmap以获取所有相关的标签,然后加入回另一个帖子(p2)以获取这些相关标签所指向的帖子。

使用GROUP BY丢弃所有加入的副本,你就在那里。