简体   繁体   English

用户变量可以在 MySQL 5.5 中从前一行中选择值,但在 5.6 中它似乎以不同的顺序运行查询的 SELECT 部分

[英]User-variable to select value from previous row fine in MySQL 5.5 but in 5.6 it seems to be running the SELECT part of the query in a different order

I have a rather unusual issue which has come up when moving to a staging server from a local environment.从本地环境移动到临时服务器时出现了一个相当不寻常的问题。 The MySQL version is different but I am unable to find any reason why this issue would have occurred. MySQL 版本不同,但我无法找到发生此问题的任何原因。

The code I am using is:我正在使用的代码是:

DECLARE _first_event_time datetime;

SELECT event_time INTO _first_event_time
FROM session_events
WHERE session_id = _session_id
ORDER BY event_id ASC LIMIT 0,1;

-- Select Data

SELECT event_id,
event_time,
timediff(event_time, _first_event_time) AS event_time_from_start,
(@previous := unix_timestamp(event_time) - @previous) AS event_duration,
(@previous := unix_timestamp(event_time)) AS previous_event_timestamp
FROM session_events e,

(SELECT @previous:=0) c
ORDER BY event_id ASC LIMIT 0, 400;

What I would expect is in the following results, which is what I am getting from 5.5 running on my DEV version running MAMP:我期望的是以下结果,这是我从运行 MAMP 的 DEV 版本上运行的 5.5 中得到的结果:

+----------+------------------+-----------------------+----------------+--------------------------+
| event_id |    event_time    | event_time_from_start | event_duration | previous_event_timestamp |
+----------+------------------+-----------------------+----------------+--------------------------+
|     5074 | 24/09/2015 20:35 | 00:00:00              |     1443123315 |               1443123315 |
|     5075 | 24/09/2015 20:35 | 00:00:02              |              2 |               1443123317 |
|     5076 | 24/09/2015 20:35 | 00:00:03              |              1 |               1443123318 |
|     5077 | 24/09/2015 20:35 | 00:00:03              |              0 |               1443123318 |
|     5078 | 24/09/2015 20:35 | 00:00:04              |              1 |               1443123319 |
|     5079 | 24/09/2015 20:35 | 00:00:05              |              1 |               1443123320 |
|     5080 | 24/09/2015 20:35 | 00:00:06              |              1 |               1443123321 |
|     5081 | 24/09/2015 20:35 | 00:00:06              |              0 |               1443123321 |
|     5082 | 24/09/2015 20:35 | 00:00:07              |              1 |               1443123322 |
|     5083 | 24/09/2015 20:35 | 00:00:08              |              1 |               1443123323 |
|     5084 | 24/09/2015 20:35 | 00:00:09              |              1 |               1443123324 |
|     5085 | 24/09/2015 20:35 | 00:00:10              |              1 |               1443123325 |
+----------+------------------+-----------------------+----------------+--------------------------+

But instead the data is coming out like this (please note that the data values are different as I have created the same values on both servers but you can see where the data is being offset, the code in the stored procedure is identical on both servers):但是数据是这样出来的(请注意,数据值是不同的,因为我在两台服务器上创建了相同的值,但您可以看到数据被偏移的位置,存储过程中的代码在两台服务器上是相同的):

+----------+------------------+-----------------------+----------------+--------------------------+
| event_id |    event_time    | event_time_from_start | event_duration | previous_event_timestamp |
+----------+------------------+-----------------------+----------------+--------------------------+
|     5307 | 24/09/2015 20:32 | 00:00:00              |            -17 |               1443123174 |
|     5308 | 24/09/2015 20:33 | 00:00:07              |     1443123181 |               1443123181 |
|     5309 | 24/09/2015 20:33 | 00:00:08              |             -7 |               1443123182 |
|     5310 | 24/09/2015 20:33 | 00:00:09              |              2 |               1443123183 |
|     5311 | 24/09/2015 20:33 | 00:00:11              |              3 |               1443123185 |
|     5312 | 24/09/2015 20:33 | 00:00:12              |              3 |               1443123186 |
|     5313 | 24/09/2015 20:33 | 00:00:13              |              2 |               1443123187 |
|     5314 | 24/09/2015 20:33 | 00:00:14              |              2 |               1443123188 |
|     5315 | 24/09/2015 20:33 | 00:00:15              |              2 |               1443123189 |
|     5316 | 24/09/2015 20:33 | 00:00:15              |              1 |               1443123189 |
|     5317 | 24/09/2015 20:33 | 00:00:17              |              2 |               1443123191 |
|     5318 | 24/09/2015 20:33 | 00:00:18              |             18 |               1443123192 |
+----------+------------------+-----------------------+----------------+--------------------------+

The timezone shouldn't make a difference as this is being run from data and a stored procedure.时区不应该有什么不同,因为这是从数据和存储过程运行的。 I have also tried changing from a timestamp to just using a datediff using the follow:我还尝试使用以下方法从时间戳更改为仅使用 datediff:

, ( TIME_TO_SEC(TIMEDIFF(event_time, @previous))) AS event_duration
, ( @previous := event_time ) AS previous_event_timestamp

Looking into this a bit further it seems to be that issue is somewhere with the ORDER BY clause, it seems to be selecting the results in an unsorted order when populating the @previous field on the initial run through on this server as if I remove the ORDER BY clause and just set @previous to event_time then the order is the one that is used that is causing the issue.进一步研究一下,似乎问题出在 ORDER BY 子句的某个地方,在此服务器上的初始运行时填充 @previous 字段时,它似乎以未排序的顺序选择结果,就好像我删除了ORDER BY 子句,只需将 @previous 设置为 event_time,那么所使用的顺序就是导致问题的顺序。

If I run just a select statement without the @previous and no ORDER BY clause the dataset returned by the 5.6 server seems to match the unusual order being shown in the 2nd example where the @previous seems to be picking random values.如果我只运行一个没有@previous 且没有 ORDER BY 子句的 select 语句,则 5.6 服务器返回的数据集似乎与第二个示例中显示的异常顺序相匹配,其中 @previous 似乎正在选择随机值。

I can only thing that the part of the SELECT statement that is running through the data and setting the @previous value is running first then when it returns to data it then runs the ORDER BY which is where the issue is coming from.我只能认为 SELECT 语句中运行数据并设置 @previous 值的部分首先运行,然后当它返回数据时运行 ORDER BY,这就是问题的来源。

Looking through the MySQL manual I have not found anything (at least not what I have been able to attribute to why this is happening) between 5.5 and 5.6.查看 MySQL 手册,我在 5.5 和 5.6 之间没有发现任何东西(至少不是我能够归因于发生这种情况的原因)。 I presume there is a way to get this working.我想有办法让这个工作。

Any suggestions would be greatly appreciated as I can not figure out why it is electing in the order it is prior to the ORDER BY clause.任何建议将不胜感激,因为我无法弄清楚为什么它按照 ORDER BY 子句之前的顺序进行选择。

MySQL explicitly warns against using variables and assigning them in different expressions in the same select . MySQL明确警告不要在同一个select中使用变量并在不同的表达式中分配它们。 I would suggest you do this using a subquery:我建议您使用子查询执行此操作:

SELECT t.*,
       (unix_timestamp(event_time) - previous_event_timestamp) as event_duration
FROM (SELECT event_id, event_time,
             timediff(event_time, _first_event_time) AS event_time_from_start,
             if((@pp := @p) = null, null, -- never happens
                if(@p := unix_timestamp(event_time), @pp, @pp)
               ) AS previous_event_timestamp
      FROM session_events e CROSS JOIN
           (SELECT @p := 0, @pp := 0) c
      ORDER BY event_id ASC
      LIMIT 0, 400
     ) t;

The if logic is just a way of putting the assignments in the same statement. if逻辑只是将赋值放在同一语句中的一种方式。 The first assigns @pp to be the current previous value (in @p ).第一个将@pp分配为当前的先前值(在@p )。 The second reassign @p , and then returns @pp .第二个重新分配@p ,然后返回@pp

The outer query then does the calculations on the value.然后外部查询对值进行计算。

The documentation says: 文档说:

As a general rule, other than in SET statements, you should never assign a value to a user variable and read the value within the same statement.作为一般规则,除了在 SET 语句中,您不应该为用户变量赋值并在同一语句中读取该值。

It is best to avoid "features" that the documentation explicitly warns against using.最好避免使用文档明确警告不要使用的“功能”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM