按下一个和上一个顺序

时间:2019-02-12 15:54:17

标签: mysql sql sql-order-by

我在MySQL中具有以下信息的SQL表:

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查询来按升序将其按下一列或按上一列的降序进行排序,其中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 :(得分:1)

嗨,我找到了一个有解决方案的程序。 当我有这样的桌子时:

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表( rows_count )中选择行数
  • 选择最小值(不包含null)的下一个值( next_value ),并将其中的行插入到临时表中
  • 循环中正在保存next_value供下次迭代搜索
  • 以及知道何时停止的迭代次数(迭代次数
  • 使用临时计数器插入临时表中的行,因为最后它将有助于排序
  • 最后,简单返回所有从temp表排序的数据

您可以通过以下方式调用它:

call zz_sort_test;

我使用mysql 5.7.18

对其进行了测试

编辑: 我编辑了答案,因此第一个选定的行将是 prev value = NULL的行 我添加了LIMIT 1,用于prev = NULL的行多于一个的情况