MySQL: последовательная нумерация столбцов на основе изменений в другом столбце - PullRequest
0 голосов
/ 08 октября 2018

Если у меня есть таблица со следующими столбцами и значениями, упорядоченная по parent_id:

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

И я хочу заполнить line_no последовательным числом, которое начинается с 1 каждый раз, когдазначение 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 каждый раз, когда добавляется новая запись.Мне просто нужно обновить записи, которые уже существуют.

Ответы [ 3 ]

0 голосов
/ 08 октября 2018

Вы можете использовать подзапрос, если 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;
0 голосов
/ 08 октября 2018

Большинство версий 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;
0 голосов
/ 08 октября 2018

Или немного больше старой школы ...

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 |
    +----+-----------+------+------+    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...