行编号(@i:= @ i + 1)无法按预期工作

时间:2014-10-15 23:51:43

标签: mysql

SET @i := 0;
SELECT posts.post_id,
       members.member_joined,
       @i := @i + 1
FROM   posts LEFT JOIN members
             ON posts.member_id = members.member_id
WHERE posts.topic_id = 1
ORDER BY posts.post_created ASC;

该查询返回以下结果集:

+---------+---------------------+--------------+
| post_id | member_joined       | @i := @i + 1 |
+---------+---------------------+--------------+
|       1 | 2014-10-14 20:28:15 |            1 |
+---------+---------------------+--------------+
|       3 | 2014-10-14 20:28:15 |            4 |
+---------+---------------------+--------------+
|       4 | 2014-10-14 20:28:15 |            5 |
+---------+---------------------+--------------+
|       5 | 2014-10-14 20:28:15 |            6 |
+---------+---------------------+--------------+
|      14 | 2014-10-14 20:28:15 |            7 |
+---------+---------------------+--------------+
|      17 | 2014-10-14 20:28:15 |            8 |
+---------+---------------------+--------------+
|      35 | 2014-10-14 20:28:15 |            9 |
+---------+---------------------+--------------+
|      37 | 2014-10-14 20:28:15 |            2 | -- What's the 2 doing down here?
+---------+---------------------+--------------+
|      42 | 2014-10-14 20:28:15 |            3 | -- Ditto.
+---------+---------------------+--------------+

正如你所看到的,对于一些我不知道的原因,数字2和3出现在结果集的最底部,而它们不应该出现。

如果我注释掉 members.member_joined 这一行:

SET @i := 0;
SELECT posts.post_id,
       -- members.member_joined,
       @i := @i + 1
FROM   posts LEFT JOIN members
             ON posts.member_id = members.member_id
WHERE posts.topic_id = 1
ORDER BY posts.post_created ASC;

现在结果集符合预期:

+---------+--------------+
| post_id | @i := @i + 1 |
+---------+--------------+
|       1 |            1 |
+---------+--------------+
|       3 |            2 |
+---------+--------------+
|       4 |            3 |
+---------+--------------+
|       5 |            4 |
+---------+--------------+
|      14 |            5 |
+---------+--------------+
|      17 |            6 |
+---------+--------------+
|      35 |            7 |
+---------+--------------+
|      37 |            8 |
+---------+--------------+
|      42 |            9 |
+---------+--------------+

我无法绕过这个。什么可能是错的?

2 个答案:

答案 0 :(得分:5)

你的订单最有可能导致计数被关闭。在选择被finsihed后执行ORDER BY,这样它可以重新排序你的计数。尝试将它放在子查询中。

SET @i := 0;
SELECT post_id, member_joined, @i := @i + 1
FROM
(   SELECT p.post_id, m.member_joined
    FROM posts p
    LEFT JOIN members m ON p.member_id = m.member_id
    WHERE p.topic_id = 1
    ORDER BY p.post_created ASC
)t;

以这种方式思考.. SELECT to WHERE从表中拉出...所以任何特定的要求都可以在WHERE中.. GROUP BY到最后是在请求完成之后你正在改变结果回来了...所以这就是为什么订单可以导致问题......当你加入选择中加入的成员时,它会返回得到计数然后按日期重新排序的结果

注意:

MySQL DOCS对此很清楚:

  

作为一般规则,您不应该为用户变量赋值   并在同一语句中读取值。你可能会得到   你期望的结果,但这不能保证。的顺序   涉及用户变量的表达式的评估是未定义的   可能会根据给定声明中包含的元素进行更改;   另外,这个顺序不保证是相同的   MySQL服务器的版本。在SELECT @ a,@ a:= @ a + 1,...,你可以   认为MySQL会首先评估@a然后做一个任务   第二。但是,更改语句(例如,通过添加   GROUP BY,HAVING或ORDER BY子句可能导致MySQL选择一个   执行计划具有不同的评估顺序。

答案 1 :(得分:0)

之前有过类似的问题。将LEFT JOIN更改为INNER JOIN解决了这个问题。

详细信息如下: https://pastebin.com/br3TNFBb