Привет, я нашел решение с процедурой.когда у меня есть такая таблица:
CREATE TABLE `zz_test` (
`id` int(11) NOT NULL,
`prev` int(11) DEFAULT NULL,
`next` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
и записи:
INSERT INTO `zz_test` VALUES ('1', '7', '2');
INSERT INTO `zz_test` VALUES ('2', '1', '3');
INSERT INTO `zz_test` VALUES ('3', '2', '6');
INSERT INTO `zz_test` VALUES ('4', '6', '5');
INSERT INTO `zz_test` VALUES ('5', '4', null);
INSERT INTO `zz_test` VALUES ('6', '3', '4');
INSERT INTO `zz_test` VALUES ('7', null, '1');
, ее можно отсортировать по этой процедуре:
DROP PROCEDURE IF EXISTS zz_sort_test;
CREATE PROCEDURE zz_sort_test()
BEGIN
DECLARE next_value INT DEFAULT 1;
DECLARE rows_count INT DEFAULT 0;
DECLARE iterations INT DEFAULT 0;
DECLARE cid, cnext, cprev INT DEFAULT NULL;
DROP TEMPORARY TABLE IF EXISTS sorted;
CREATE TEMPORARY TABLE IF NOT EXISTS sorted (iter INT, id INT, prev INT, next INT);
SELECT COUNT(1) INTO rows_count FROM zz_test;
#first row
SELECT next INTO next_value FROM zz_test WHERE prev IS NULL LIMIT 1;
SELECT id, prev, next INTO cid, cprev, cnext FROM zz_test WHERE next_value = next;
INSERT INTO sorted (iter, id, prev, next) VALUES (-1, cid, cprev, cnext);
loopy: LOOP
SET iterations = iterations + 1;
IF rows_count = iterations THEN
LEAVE loopy;
END IF;
SELECT id, prev, next INTO cid, cprev, cnext FROM zz_test WHERE next_value = id;
SET next_value := cnext;
INSERT INTO sorted (iter, id, prev, next) VALUES (iterations, cid, cprev, cnext);
END LOOP loopy;
SELECT id, prev, next FROM sorted ORDER BY iter;
END
, чтобы объяснить, что происходиттам:
- создает временную таблицу для хранения выбранных данных ( отсортировано )
- выбирает количество строк в таблице zz_test ( lines_count )
- выбирает минимальное (без нуля) следующее значение ( next_value ) и вставляет строку с ним во временную таблицу
- в цикле сохраняет значение next_value для следующей итерации для поискана
- и количество итераций, чтобы знать, когда нужно остановиться ( итераций )
- строк во временной таблице вставляются с счетчиком итераций, потому что в конце это поможет с сортировкой
- в конце, просто вернуть все отсортированные из временной таблицы
Вы можете вызвать это по:
call zz_sort_test;
я проверил это с помощью mysql 5.7.18
РЕДАКТИРОВАТЬ: я отредактировал ответ, поэтому первая выбранная строка будет один умh prev value = NULL я добавил LIMIT 1 для ситуаций, когда будет более одной строки с prev = NULL