заказ на следующий и предыдущий - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть таблица SQL в MySQL со следующей информацией:

id | prev | next
1  | 7    |  2
2  | 1    |  3
3  | 2    |  6
4  | 6    |  5
5  | 4    |  null
6  | 3    |  4
7  | null |  1

Я хочу использовать запрос SQL, чтобы упорядочить его по возрастанию по следующему столбцу или по убыванию по столбцу prev, где next - указатель на следующую строкуа previous - указатель на предыдущую строку, поэтому, если я захочу, например, упорядочить по возрастанию, я получу следующий результат:

id | prev | next
7  | null |  1
1  | 7    |  2
2  | 1    |  3
3  | 2    |  6
6  | 3    |  4
4  | 6    |  5
5  | 4    |  null

Так как это сделать?

Обновление:Первая таблица упорядочена по id, но я хочу упорядочить ее таким образом, чтобы я получил вторую таблицу, вторая таблица получается при переходе к следующему значению, поэтому первая строка равна 7 (id = 7), потому что prev равно null ивторой - 1, потому что следующий столбец первой строки - 1, а затем третья строка - 2, потому что 2 - значение следующего столбца второй строки и т. д.

1 Ответ

0 голосов
/ 13 февраля 2019

Привет, я нашел решение с процедурой.когда у меня есть такая таблица:

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

...