MySQL SELECT顺序的值为2列

时间:2016-08-30 11:14:04

标签: mysql

我有一张这样的表:

CREATE TABLE rows(
    UniqueID VARCHAR(225),
    Previous VARCHAR(225),
    Next VARCHAR(225)
);

内容如下:

+----------+-----------+-----------+
| UniqueID | Previous  | Next      |
+----------+-----------+-----------+
|    676   | undefined |       219 |
|    890   |       219 | undefined |
|    219   |       676 |       890 |
+----------+-----------+-----------+

如您所见,这些行包含UID,PreviousNext列引用这些行。

我现在想要的是编写一个SELECT *语句,它将按PreviousNext字段排序所有结果。 undefined值标记结束元素。我怎么能实现这一目标?在上面显示的表格的情况下,我想要的顺序是那里显示的,最后2行位置交换,因此行X的Next指向行Y的UID ,其Previous指向行X的UID等。

3 个答案:

答案 0 :(得分:2)

您尝试创建的是递归查询。不幸的是,MySQL并没有让这很容易。如果父母的索引总是大于孩子,那么有相对简单的解决方案,但这不是这种情况。讨论这类问题有几个问题。以下问题的答案探讨了尝试此类查询的不同方法,包括使用存储过程。

How to do the Recursive SELECT query in MySQL?

使用存储过程的想法,您可以尝试类似:

CREATE PROCEDURE getInOrder()
  BEGIN
    DECLARE child_id VARCHAR(256);
    DECLARE prev_id VARCHAR(256);
    SELECT UniqueID INTO prev_id FROM rows WHERE Previous = 'undefined';
    SELECT `Next` INTO child_id
    FROM rows WHERE UniqueID = prev_id;
    CREATE TEMPORARY TABLE IF NOT EXISTS temp_table AS (SELECT * FROM rows WHERE 1=0);
    TRUNCATE TABLE temp_table;
    WHILE child_id <> 'undefined' DO
      INSERT INTO temp_table SELECT * FROM rows WHERE UniqueID = prev_id;
      SET prev_id = child_id;
      SELECT `Next` INTO child_id
      FROM rows WHERE UniqueID = prev_id;
    END WHILE;
    INSERT INTO temp_table SELECT * FROM rows WHERE UniqueID = prev_id;
    SELECT * FROM temp_table;
  END;

然后,您可以调用存储过程以按顺序检索表。

工作示例:http://sqlfiddle.com/#!9/085dec/2

答案 1 :(得分:0)

ORDER BY IFNULL(prev, ''),         -- some value lower than the rest
         IFNULL(next, 'zzzzz')     -- some value higher than all values

(从技术上讲,第一部分可能只是prev,没有IFNULL。)

如果id确实是数字,则应使用数字数据类型,例如INT UNSIGNED。如果他们真的是字符串,你需要225吗?

这假定prev&lt;下一个 - 是否一定如此?似乎任意链接可能无法保持这一点。如果您需要next根据UniqueId加载下一行,则代码要复杂得多。

答案 2 :(得分:0)

我认为这个要求缺乏细节。

但是,您希望最终结果是这样的吗?

+----------+-----------+-----------+
| UniqueID | Previous  | Next      |
+----------+-----------+-----------+
|    676   | undefined |       219 |
|    219   |       676 |       890 |
|    890   |       219 | undefined |
+----------+-----------+-----------+

如果我是对的,你可以用(我将表命名为demo)来实现它:

SELECT d.* FROM (
    SELECT UniqueID, IF(Previous IS NULL, -1, Previous) AS Previous, IF(Next   IS NULL, 999999999999, Next) as Next
    FROM demo
)t
JOIN demo d ON d.UniqueID = t.UniqueID
ORDER BY t.Next, t.Previous
;

因此,当PreviousNULL时,您将其设为-1,以确保他是列表中的第一个,当NextNULL时,您将其放入非常高的值,以确保它将是列表中的最后一个...然后您只需按PreviousNext订购查询。

我必须强调,这个解决方案专注于提供的数据。