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

llew8vvj  于 2021-06-18  发布在  Mysql
关注(0)|答案(3)|浏览(355)

如果我有一个包含以下列和值的表,按 parent_id :

id    parent_id    line_no
--    ---------    -------
1     2            
2     2
3     2
4     3
5     4
6     4

我想填充 line_no 每次 parent_id 变化:

id    parent_id    line_no
--    ---------    -------
1     2            1
2     2            2
3     2            3
4     3            1
5     4            1
6     4            2

查询或存储过程是什么样子的?
注意:我应该指出我只需要做一次。在我的php代码中有一个新函数,可以自动创建 line_no 每次添加新记录时。我只需要更新已经存在的记录。

q1qsirdb

q1qsirdb1#

或者,更老派一点。。。

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 |
    +----+-----------+------+------+
8gsdolmq

8gsdolmq2#

如果 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;
h9vpoimq

h9vpoimq3#

大多数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;

相关问题