MySQL:根据不同列中的更改对列进行顺序编号

时间:2018-10-08 16:23:08

标签: mysql sql mariadb

如果我有一个包含以下列和值的表,按data: datafromNetworking排序:

parent_id

我想用id parent_id line_no -- --------- ------- 1 2 2 2 3 2 4 3 5 4 6 4 每次更改时从1开始的序列号填充line_no

parent_id

查询或存储过程是什么样的?

注意:我应该指出,我只需要这样做一次。我的PHP代码中有一个新函数,每次添加新记录时,该函数都会自动创建id parent_id line_no -- --------- ------- 1 2 1 2 2 2 3 2 3 4 3 1 5 4 1 6 4 2 。我只需要更新已经存在的记录即可。

3 个答案:

答案 0 :(得分:1)

或者,是一所老学校...

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,parent_id INT NOT NULL
);

INSERT INTO my_table VALUES
(1,    2), 
(2 ,    2), 
(3 ,    2), 
(4 ,    3), 
(5 ,    4), 
(6 ,    4);

SELECT x.*
     , CASE WHEN @prev = parent_id THEN @i := @i+1 ELSE @i := 1 END i
     , @prev := parent_id prev 
  FROM my_table x
     , (SELECT @prev:=null,@i:=0) vars 
 ORDER 
    BY parent_id,id;
    +----+-----------+------+------+
    | id | parent_id | i    | prev |
    +----+-----------+------+------+
    |  1 |         2 |    1 |    2 |
    |  2 |         2 |    2 |    2 |
    |  3 |         2 |    3 |    2 |
    |  4 |         3 |    1 |    3 |
    |  5 |         4 |    1 |    4 |
    |  6 |         4 |    2 |    4 |
    +----+-----------+------+------+    

答案 1 :(得分:1)

大多数MySQL版本不支持row_number()。因此,您可以使用变量来执行此操作。但是您必须非常小心。 MySQL不保证select中变量的求值顺序,因此不应为变量分配不同表达式中的引用。

所以:

select t.*,
       (@rn := if(@p = parent_id, @rn + 1,
                  if(@p := parent_id, 1, 1)
                 )
       ) as line_no
from (select t.* from t order by id) t cross join
     (select @p := 0, @rn := 0) params;

可能不需要对表进行排序的子查询。在5.7版附近的某个地方,使用变量时变得很有必要。

编辑:

使用变量更新很有趣。在这种情况下,我只会在上面使用子查询:

update t join
       (select t.*,
               (@rn := if(@p = parent_id, @rn + 1,
                          if(@p := parent_id, 1, 1)
                         )
               ) as new_line_no
        from (select t.* from t order by id) t cross join
             (select @p := 0, @rn := 0) params
       ) tt
       on t.id = tt.id
    set t.line_no = tt.new_line_no;

答案 2 :(得分:0)

如果row_number()无效,则可以使用子查询:

select t.*, 
       (select count(*)
        from table t1
        where t1.parent_id = t.parent_id and t1.id <= t.id
       ) as line_no
from table t;