当使用的变量和查询发生更改时,MySQL会重复Resultl
奇怪的事。有一张桌子:当使用的变量和查询发生更改时,MySQL会重复Resultl,mysql,variables,Mysql,Variables,奇怪的事。有一张桌子: +-----------------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------------+---------------+------+-----+---------+-------+ | date_time | datetime(3) | N
+-----------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------+------+-----+---------+-------+
| date_time | datetime(3) | NO | PRI | NULL | |
关于数据:
+-------------------------+
| date_time |
+-------------------------+
| 2017-01-02 00:00:00.000 |
| 2017-01-03 00:00:00.000 |
| 2017-01-04 00:00:00.000 |
| 2017-01-05 00:00:00.000 |
| 2017-01-06 00:00:00.000 |
| 2017-01-08 00:00:00.000 |
| 2017-01-09 00:00:00.000 |
| 2017-01-10 00:00:00.000 |
| 2017-01-11 00:00:00.000 |
| 2017-01-12 00:00:00.000 |
+-------------------------+
10 rows in set (0.00 sec)
如果我这样问:
SELECT
@date_from := FIRST_VALUE (DATE(`date_time`)) OVER (
ORDER BY `date_time`
) AS `Date From`,
@date_to := LAST_VALUE(DATE(`date_time`)) OVER (
ORDER BY `date_time`
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) AS `Date To`,
@date_diff := TIMESTAMPDIFF(DAY, @date_from, @date_to) AS `Period [D]`
FROM
test
WHERE
`date_time`
BETWEEN
'2017-01-02'
AND
'2017-01-12'
LIMIT 1;
我得到的结果是:
+------------+------------+------------+
| Date From | Date To | Period [D] |
+------------+------------+------------+
| 2017-01-02 | 2017-01-12 | 10 |
+------------+------------+------------+
1 row in set, 3 warnings (0.00 sec)
如预期,但有3个警告(每个警告都是同一句话):
警告| 1287 |在表达式中设置用户变量是错误的
已弃用,将在将来的版本中删除。考虑
备选方案:“设置变量=表达式,…”或“选择表达式”
“转换为变量”
当我在某个日期结束时更改时:
WHERE
`date_time`
BETWEEN
'2017-01-02'
AND
'2017-01-10' -- Changed
LIMIT 1;
我得到的结果与之前相同(错误):
但现在有趣的是:如果我回复执行相同的查询(截止日期2017-01-10),我会得到正确的结果:
+------------+------------+------------+
| Date From | Date To | Period [D] |
+------------+------------+------------+
| 2017-01-02 | 2017-01-10 | 8 |
+------------+------------+------------+
1 row in set, 3 warnings (0.00 sec)
@date_diff后来在其他语句中使用,但我删除了所有不相关的代码
如何重写select部分,这样就不会出现警告,为什么我在第一次执行查询时得到了错误的句点(@date\u diff),但在第二次运行时得到了正确的句点?如何解决这个问题
我正在使用MySQL 8。代码查询是从MySQL CLI客户端运行的。这就是为什么他们要删除变量的这种用法。从: 涉及用户变量的表达式的求值顺序为 未定义。例如,不能保证
选择@a,@a:=@a+1
首先计算@a,然后执行赋值
无法保证选择中变量赋值的执行顺序,因此第二个查询中出现的情况是@date\u diff
在更新@date\u to
的值之前进行计算。解决此问题的最简单方法是删除变量:
SELECT
FIRST_VALUE(DATE(`date_time`)) OVER (ORDER BY `date_time`) AS `Date From`,
LAST_VALUE(DATE(`date_time`)) OVER (ORDER BY `date_time` ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS `Date To`,
TIMESTAMPDIFF(DAY, FIRST_VALUE(DATE(`date_time`)) OVER (ORDER BY `date_time`), LAST_VALUE(DATE(`date_time`)) OVER (ORDER BY `date_time` ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)) AS `Period [D]`
FROM test
WHERE `date_time` BETWEEN '2017-01-02' AND '2017-01-12'
LIMIT 1
或者使用子查询使其更整洁:
SELECT `Date From`, `Date To`, TIMESTAMPDIFF(DAY, `Date From`, `Date To`) AS `Period [D]`
FROM (SELECT
FIRST_VALUE(DATE(`date_time`)) OVER (ORDER BY `date_time`) AS `Date From`,
LAST_VALUE(DATE(`date_time`)) OVER (ORDER BY `date_time` ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS `Date To`
FROM test
WHERE `date_time` BETWEEN '2017-01-02' AND '2017-01-12'
LIMIT 1) t
如果使用警告的替代方式,变量赋值的顺序是否正确<代码>考虑备选方案:“设置变量=表达式,…”或“将表达式选择为变量”
?我想坚持使用变量,因为没有变量以后的计算会有点混乱。@Jimmix如果你执行一系列SET
语句,它们肯定会按顺序执行。但一般来说,SELECT
中表达式的求值顺序不受保证。您可能需要考虑使用存储过程,或者您可以不断嵌套子查询以强制评估顺序(因为嵌套子查询必须在外部查询之前进行评估)。
SELECT `Date From`, `Date To`, TIMESTAMPDIFF(DAY, `Date From`, `Date To`) AS `Period [D]`
FROM (SELECT
FIRST_VALUE(DATE(`date_time`)) OVER (ORDER BY `date_time`) AS `Date From`,
LAST_VALUE(DATE(`date_time`)) OVER (ORDER BY `date_time` ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS `Date To`
FROM test
WHERE `date_time` BETWEEN '2017-01-02' AND '2017-01-12'
LIMIT 1) t