Как увеличить идентификатор на основе поля, имеющего определенное значение, идущее строка за строкой - PullRequest
0 голосов
/ 05 октября 2019

Я импортирую данные, для которых группам строк должен быть присвоен идентификатор, но во входных данных нет ничего уникального и общего для них. Имеется известный индикатор первой строки группы и того, что данные расположены по порядку, поэтому мы можем пошагово шаг за шагом устанавливать идентификатор, а затем увеличивать этот идентификатор всякий раз, когда этот индикатор найден. Я сделал это, однако это невероятно медленно, поэтому есть ли лучший способ сделать это в mysql, или мне лучше, возможно, предварительно обрабатывать текстовые данные, идущие построчно, чтобы добавить идентификатор.

Пример поступления данных, мне нужно увеличивать идентификатор всякий раз, когда мы видим «NEW»

id,linetype,number,text
1,NEW,1234,sometext
2,CONTINUE,2412,anytext
3,CONTINUE,1,hello
4,NEW,2333,bla bla
5,CONTINUE,333,hello
6,NEW,1234,anything

Так что я получу

id,linetype,number,text,group_id
1,NEW,1234,sometext,1
2,CONTINUE,2412,anytext,1
3,CONTINUE,1,hello,1
4,NEW,2333,bla bla,2
5,CONTINUE,333,hello,2
6,NEW,1234,anything,3

Iя пробовал хранимую процедуру, где я иду по очереди, обновляя информацию по ходу, но она очень медленная.

select count(*) from mytable into n;
set i=1;
while i<=n do
  select linetype into l_linetype from mytable where id = i;
  if l_linetype = "NEW" then
    set l_id = l_id + 1;
  end if;
  update mytable set group_id = l_id where id = i;
end while;

Нет ошибок, это просто то, что я могу построчно читать и писать текстовый файли сделайте через секунду, пока в mysql это занимает 100 секунд, было бы неплохо, если бы в mysql был способ сделать это достаточно быстро, поэтому отдельная предварительная обработка не требовалась.

Ответы [ 2 ]

0 голосов
/ 05 октября 2019

Для MySql 8.0+ вы можете использовать оконную функцию SUM ():

select *,
  sum(linetype = 'NEW') over (order by id) group_id
from tablename  

См. demo . Для предыдущих версий вы можете смоделировать эту функцию с помощью переменной:

set @group_id := 0;
select *,
  @group_id := @group_id + (linetype = 'NEW') group_id
from tablename 
order by id

См. demo .

Результаты:

| id  | linetype | number | text     | group_id |
| --- | -------- | ------ | -------- | -------- |
| 1   | NEW      | 1234   | sometext | 1        |
| 2   | CONTINUE | 2412   | anytext  | 1        |
| 3   | CONTINUE | 1      | hello    | 1        |
| 4   | NEW      | 2333   | bla bla  | 2        |
| 5   | CONTINUE | 333    | hello    | 2        |
| 6   | NEW      | 1234   | anything | 3        |
0 голосов
/ 05 октября 2019

В отсутствие MySQL 8+ (недоступность оконных функций) вы можете использовать вместо этого коррелированный подзапрос:

РЕДАКТИРОВАТЬ : как указано @Paul в комментариях,

SELECT t1.*, 
       (SELECT COUNT(*) 
        FROM your_table t2
        WHERE t2.id <= t1.id 
          AND t2.linetype = 'NEW'
       ) group_id
FROM your_table t1

Приведенный выше запрос может быть более производительным , если мы определим следующий составной индекс (linetype, id). Порядок столбцов важен, потому что у нас есть условие Range для id.

Ранее:

SELECT t1.*, 
       (SELECT SUM(t2.linetype = 'NEW') 
        FROM your_table t2
        WHERE t2.id <= t1.id
       ) group_id
FROM your_table t1

Выше запроса требует индексации на id.


Другой подход, использующий пользовательские переменные (переменные сеанса), будет выглядеть так:

SELECT 
  t1.*, 
  @g := IF(t1.linetype = 'NEW', @g + 1, @g) AS group_id
FROM your_table t1 
CROSS JOIN (SELECT @g := 0) vars 
ORDER BY t1.id

Это похоже на метод зацикливания, в котором мы используем переменные сеанса , предыдущее значение которого доступно во времярасчет следующей строки в течение SELECT. Итак, мы инициализируем переменную @g равной 0, а затем вычисляем ее строка за строкой. Если мы можем встретить строку с NEW типом линии, мы увеличиваем ее, иначе используем значение предыдущей строки. Вы также можете проверить https://stackoverflow.com/a/53465139/2469308 для получения дополнительной информации и предостережений, которые следует учитывать при использовании этого подхода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...