Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当使用的变量和查询发生更改时,MySQL会重复Resultl_Mysql_Variables - Fatal编程技术网

当使用的变量和查询发生更改时,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