Упорядочивание строк результата MySQL на основе поля «next_id»

#mysql #sql #sorting

#mysql #sql #сортировка

Вопрос:

В настоящее время я работаю с таблицей базы данных, которая структурирована следующим образом:

  ______________________________
|  id  |  content  |  next_id  |
|------|-----------|-----------|
|  1   |  (value)  |     4     |
|  2   |  (value)  |     1     |
|  3   |  (value)  |   (NULL)  |
|  4   |  (value)  |     3     |
 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  

Значение next_id поля определяет идентификатор строки данных, которая должна следовать за ним. Значение NULL означает, что за ним не следует ни одна строка.

Есть ли способ, которым я могу запросить базу данных таким образом, чтобы в результате строки были упорядочены с использованием этого метода? Например, в случае, который я привел выше, строки должны быть возвращены в таком порядке, чтобы идентификаторы были в этом порядке: 2 , 1 , 4 , 3 . Я ищу решение, которое может сделать это независимо от количества строк в этой последовательности.

Я знаю, что можно изменить порядок результатов после извлечения их из базы данных (используя язык программирования, с которым я работаю), но я надеюсь, что есть способ, которым я могу сделать это в SQL.

Комментарии:

1. Это очень похоже на вложение с неопределенной глубиной уровня.

2. Используйте процедуру или свой язык программирования.

3. Мне кажется, вам нужно преобразовать вашу структуру данных для использования вложенных наборов, тогда такого рода запросы были бы проще.

4. Какие существуют ограничения? Т.Е. могу ли я иметь (1,2) и (2,1) ? Что произойдет, если у меня есть (1,4) , (4,2) и (2,1) ?

5. @Thomas вы можете предположить, что данные в базе данных правильно сформированы; т. Е. не должно быть циклических ссылок, как вы указали в своем примере.

Ответ №1:

Я не вижу решения без такого количества самосоединений, как у вас есть строки. Вместо этого я бы построил из него вложенный набор во временной таблице, используя алгоритм push down stack, а затем извлек полное дерево.

Ответ №2:

У меня есть кое-что, что близко.

 /*one select to init the @next variable to the first row*/
select @next:= id from table1 order by isnull(next_id) asc, next_id asc limit 1;


select distinct a.id, a.next_id from table1 b
  inner join
  (
    select @rank:= id as id, @next:= next_id as next_id from table1
    where id = @next
  ) a
  on (b.id = b.id);
  

Это выводит

  ---- --------- 
| id | next_id |
 ---- --------- 
| 2  | 1       |
| 1  | 4       |
  

И затем останавливается. Если бы я только мог найти способ продолжить….

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