timestamp

问题描述 投票:0回答:1

当我在MySQL中使用 "order by "指令时,遇到了一个奇怪的事实,我想请你帮忙。

让我们看看下面的表格。

CREATE TABLE `test_nested_order_by` (
  `id` int(11) NOT NULL,
  `timestamp` int(11) NOT NULL COMMENT 'Timestamp',
  `index_continuity_month` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

insert into test_nested_order_by (id,timestamp,index_continuity_month) values (1,1583772141,0) ;
insert into test_nested_order_by (id,timestamp,index_continuity_month) values (1,1583708400,0) ;
insert into test_nested_order_by (id,timestamp,index_continuity_month) values (5,1583708400,0) ;
insert into test_nested_order_by (id,timestamp,index_continuity_month) values (4,1583708400,0) ;
insert into test_nested_order_by (id,timestamp,index_continuity_month) values (5,1583794800,0) ;
insert into test_nested_order_by (id,timestamp,index_continuity_month) values (4,1583794800,0) ;

正如你所看到的,每一行的 "index_continuity_month "列都设置了0值。

现在我想把这个值设置为:一个唯一的值,将按照id和时间戳列的升序递增。这个表看起来像:

mysql>  select * from test_nested_order_by :

+----+------------+------------------------+
| id | timestamp  | index_continuity_month |
+----+------------+------------------------+
|  1 | 1583772141 |                      2 |
|  1 | 1583708400 |                      1 |
|  5 | 1583708400 |                      5 |
|  4 | 1583708400 |                      3 |
|  5 | 1583794800 |                      6 |
|  4 | 1583794800 |                      4 |
+----+------------+------------------------+
6 rows in set (0,00 sec)

或者,如果你喜欢:

mysql> select * from test_nested_order_by order by id,timestamp ;
+----+------------+------------------------+
| id | timestamp  | index_continuity_month |
+----+------------+------------------------+
|  1 | 1583708400 |                      1 |
|  1 | 1583772141 |                      2 |
|  4 | 1583708400 |                      3 |
|  4 | 1583794800 |                      4 |
|  5 | 1583708400 |                      5 |
|  5 | 1583794800 |                      6 |
+----+------------+------------------------+

为此,我使用了这个查询。

UPDATE  test_nested_order_by t1,
(SELECT
id,
timestamp,
@last_continuity_month := @last_continuity_month +1, @last_continuity_month AS index_continuity_month

FROM test_nested_order_by, (

SELECT @last_continuity_month :=0
)SQLVars
ORDER BY id , timestamp) t2

SET t1.index_continuity_month = t2.index_continuity_month

WHERE t1.id = t2.id
      AND t1.timestamp = t2.timestamp;

但是当我看到结果时,它似乎并没有工作。

mysql> select * from test_nested_order_by order by id,timestamp ;
+----+------------+------------------------+
| id | timestamp  | index_continuity_month |
+----+------------+------------------------+
|  1 | 1583708400 |                      2 |
|  1 | 1583772141 |                      1 |
|  4 | 1583708400 |                      4 |
|  4 | 1583794800 |                      6 |
|  5 | 1583708400 |                      3 |
|  5 | 1583794800 |                      5 |
+----+------------+------------------------+
6 rows in set (0,00 sec)

我怀疑 "order by "指令没有被考虑在内(如果我从查询中删除它,结果是完全一样的)。

我们可以注意到,index_continuity_month的递增不是按照id和timestamp列的升序进行的,而是按照在表中插入行的顺序进行的。

但是,如果我只运行嵌套部分的查询。

SELECT
id,
timestamp,
@last_continuity_month := @last_continuity_month +1, @last_continuity_month AS index_continuity_month

FROM test_nested_order_by, (

SELECT @last_continuity_month :=0
)SQLVars
ORDER BY id , timestamp;

+----+------------+-----------------------------------------------------+------------------------+
| id | timestamp  | @last_continuity_month := @last_continuity_month +1 | index_continuity_month |
+----+------------+-----------------------------------------------------+------------------------+
|  1 | 1583708400 |                                                   1 |                      1 |
|  1 | 1583772141 |                                                   2 |                      2 |
|  4 | 1583708400 |                                                   3 |                      3 |
|  4 | 1583794800 |                                                   4 |                      4 |
|  5 | 1583708400 |                                                   5 |                      5 |
|  5 | 1583794800 |                                                   6 |                      6 |
+----+------------+-----------------------------------------------------+------------------------+

结果是好的!

有谁能给我解释一下问题出在哪里?更具体地说,为什么当SQL查询嵌套到另一个查询中时,它没有相同的行为?

非常感谢!

mysql
1个回答
1
投票

作为一个初学者:如果你正在运行MySQL 8.0,这是很简单的完成与 row_number():

update test_nested_order_by t
inner join (
    select 
        t.*, 
        row_number() over(order by id, timestamp) rn 
    from test_nested_order_by t
) t1 on t1.id = t.id and t1.timestamp = t.timestamp
set t.index_continuity_month  = t1.rn 

在早期的版本中,用户变量确实是一个解决方案;但是,在使用这些变量的同时,也要考虑到用户的需求。order by 是相当棘手的。这是因为 order by 通常处理 之后select 子句,所以不能保证每条记录都会被分配到 "正确 "的值。为了解决这个问题,你需要先在子查询中对表进行排序,然后设置变量。

update test_nested_order_by t
inner join (
    select t.*, @rn := @rn + 1 rn
    from (select * from test_nested_order_by order by id, timestamp) t
    cross join (select @rn := 0) x
) t1 on t1.id = t.id and t1.timestamp = t.timestamp
set t.index_continuity_month  = t1.rn 

在DB Fiddle上演示 - 两者 update 查询产生以下结果。

select * from test_nested_order_by order by id, timestamp
id 
© www.soinside.com 2019 - 2024. All rights reserved.