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

Mysql 行编号(@i:=@i+1)无法按预期工作,mysql,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; 正如你所看到的,由于一

该查询返回以下结果集:

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;
正如你所看到的,由于一些我不知道的原因,数字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;

我就是受不了这件事。可能有什么问题?

您的订单很可能导致计数关闭。。ORDER BY在查找select后执行,以便对您的计数进行重新排序。。尝试将其放入子查询中

+---------+--------------+
| post_id | @i := @i + 1 |
+---------+--------------+
|       1 |            1 |
+---------+--------------+
|       3 |            2 |
+---------+--------------+
|       4 |            3 |
+---------+--------------+
|       5 |            4 |
+---------+--------------+
|      14 |            5 |
+---------+--------------+
|      17 |            6 |
+---------+--------------+
|      35 |            7 |
+---------+--------------+
|      37 |            8 |
+---------+--------------+
|      42 |            9 |
+---------+--------------+
这样想吧。。选择要从表中拖动的位置。。。因此,任何具体要求都可以在WHERE中找到。。分组结束是在请求完成后,您正在更改返回的结果。。。这就是为什么订单会导致问题。。。当您将加入到选择中的成员包括进来时,它将返回计算结果,然后按日期重新排序

注: MySQL对此非常清楚:

一般来说,您不应该为用户变量赋值 并读取同一语句中的值。你可能会得到 你期望的结果,但这不是保证。秩序 涉及用户变量的表达式的求值未定义且 可根据给定语句中包含的元素进行更改; 此外,不保证双方的订单相同 MySQL服务器的发布。在选择@a,@a:=@a+1,…,您可以 认为MySQL将首先计算@a,然后执行赋值 第二但是,更改语句(例如,通过添加 GROUPBY、HAVING或ORDERBY子句可能会导致MySQL选择 具有不同评估顺序的执行计划


很可能是您的订单导致了计数的减少。。ORDER BY在查找select后执行,以便对您的计数进行重新排序。。尝试将其放入子查询中

+---------+--------------+
| post_id | @i := @i + 1 |
+---------+--------------+
|       1 |            1 |
+---------+--------------+
|       3 |            2 |
+---------+--------------+
|       4 |            3 |
+---------+--------------+
|       5 |            4 |
+---------+--------------+
|      14 |            5 |
+---------+--------------+
|      17 |            6 |
+---------+--------------+
|      35 |            7 |
+---------+--------------+
|      37 |            8 |
+---------+--------------+
|      42 |            9 |
+---------+--------------+
这样想吧。。选择要从表中拖动的位置。。。因此,任何具体要求都可以在WHERE中找到。。分组结束是在请求完成后,您正在更改返回的结果。。。这就是为什么订单会导致问题。。。当您将加入到选择中的成员包括进来时,它将返回计算结果,然后按日期重新排序

注: MySQL对此非常清楚:

一般来说,您不应该为用户变量赋值 并读取同一语句中的值。你可能会得到 你期望的结果,但这不是保证。秩序 涉及用户变量的表达式的求值未定义且 可根据给定语句中包含的元素进行更改; 此外,不保证双方的订单相同 MySQL服务器的发布。在选择@a,@a:=@a+1,…,您可以 认为MySQL将首先计算@a,然后执行赋值 第二但是,更改语句(例如,通过添加 GROUPBY、HAVING或ORDERBY子句可能会导致MySQL选择 具有不同评估顺序的执行计划


之前也有类似的问题。将左连接更改为内连接解决了此问题

详情如下:
之前也有类似的问题。将左连接更改为内连接解决了此问题

详情如下:

在记录已经处理和重新排序之后,我将如何重写查询,并对订单进行了很好的解释。+1。OP期望返回的结果取决于MySQL无法保证的操作顺序。让我们补充一点,这个答案中的查询之所以有效,是因为它使MySQL在执行其他操作之前先执行一些操作。但是文档给出了具体的警告,即我们观察到的用户定义变量的这种行为是不能保证的,即使是在查询重写的情况下也是如此。我将如何重写查询,并在记录已经处理和重新排序之后对order by进行了很好的解释。+1。OP期望返回的结果取决于MySQL无法保证的操作顺序。让我们补充一点,这个答案中的查询之所以有效,是因为它使MySQL在执行其他操作之前先执行一些操作。但是文档给出了具体的警告,即我们在用户定义变量中观察到的这种行为是不能保证的,即使在查询重写的情况下也是如此。您期望返回的结果取决于MySQL不能保证的操作顺序。查询的编写可能会有所不同,以使MySQL以不同的顺序执行操作。但是,即使重新编写了查询,MySQL参考手册也警告说,我们在使用用户定义变量时观察到的行为并不能得到保证。您期望返回的结果取决于MySQL不能保证的操作顺序。查询的编写可能会有所不同,以使MySQL以不同的顺序执行操作。但即使重新编写查询,MySQL Ref erence手册警告说,我们在使用用户定义变量时所观察到的行为是不能保证的。
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;