【问题标题】:How to LIMIT a JOIN?如何限制加入?
【发布时间】:2015-09-16 08:35:54
【问题描述】:

好的,经过数小时的挖掘,我仍然没有找到解决 - IMO 相当明显 - 任务的解决方案。我有posts,我想在每个帖子中查询最多 5 个comments(可能是最新的)。

所以基本上是这样的:

SELECT p.id, p.title, c.id, c.text
FROM posts p
LEFT JOIN comments c ON p.id = c.postId LIMIT 5

(伪,不起作用)

如何限制联接?

【问题讨论】:

标签: mysql sql


【解决方案1】:
SELECT  *
FROM    posts p
LEFT JOIN
        comments c
ON      c.post_id = p.id
        AND c.id >=
        COALESCE(
                (
                SELECT  ci.id
                FROM    comments ci
                WHERE   ci.post_id = p.id
                ORDER BY
                        ci.post_id DESC, ci.id DESC -- You need both fields here for MySQL to pick the right index
                LIMIT   4, 1
                ), 0
                )

comments (post_id)comments (post_id, id)(如果comments 是MyISAM)上创建一个索引,以便快速工作。

【讨论】:

  • 你能解释一下这里发生了什么吗?
  • @AronWoost:对于每个帖子,您选择第五大评论 id(如果少于 5 个 cmets,则选择 0)并选择给定帖子 id 和评论 id 等于或大于的所有 cmets第 5 个最大的(如果少于 5 个,则为 0)。
  • 按评论日期而不是 id 订购会更安全吗? (假设正在记录评论日期,即使问题中没有显示)。
  • @McAdam331:为了什么更安全?
  • @McAdam331:MySQL 不会让您有效地进行元组比较,因此您必须为此执行三个子查询。但如果有问题,这是可行的。
【解决方案2】:

这看起来像是[greatest-n-per-group] 问题。该链接指向本网站上的另一个标记问题。我将首先获取所有帖子/cmets,然后您可以将其限制为每个帖子的最新 5 个,如下所示:

SELECT p1.*, c1.*
FROM posts p1
LEFT JOIN comments c1 ON c1.post_id = p1.id
WHERE(
   SELECT COUNT(*)
   FROM posts p2
   LEFT JOIN comments c2 ON c2.post_id = p2.id
   WHERE c2.post_id = c1.post_id AND c2.commentDate >= c1.commentDate
) <= 5;

这里是另一个 reference 的主题。

【讨论】:

  • 您可能是指第 8 行中的 WHERE c2.post_id = c1.post_id AND c2.id &gt;= c1.id。还有第 3 行中的 c1 和 p1 而不是 c 和 p。
  • 我的意思不是基于帖子来连接它们,而是基于 cmets 本身。不过,您是对的,关于错过第三行的 1。
  • 虽然您可以比较日期而不是 cmets 的 id,但您仍然必须通过 post_id 关联该子查询,因为如果您通过 comment_id 执行此操作,则计数将始终返回 1,始终为
  • 我现在看到了,我已经解决了。如果 OP 发布了一些示例数据,我会在发布之前对此进行测试。
【解决方案3】:

您可以使用变量来做到这一点:

SELECT pid, title, cid, text
FROM (
  SELECT p.id AS pid, p.title, c.id AS cid, c.text,
         @row_number:= IF(@pid = p.id,
                          IF (@pid:=p.id, @row_number+1, @row_number+1),
                          IF (@pid:=p.id, 1, 1)) AS rn
  FROM posts p
  CROSS JOIN (SELECT @row_number := 0, @pid := 0) AS vars
  LEFT JOIN comments c ON p.id = c.postId 
  ORDER BY p.id ) t  <-- add comments ordering field here
WHERE t.rn <= 5

Demo here

【讨论】:

    猜你喜欢
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    • 2014-11-12
    • 2015-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-24
    相关资源
    最近更新 更多