从MySQL中选择链表

时间:2012-03-27 09:42:30

标签: mysql

我有一个MySQL表,如下所示:

> describe books;
+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| id            | int(11)      | NO   | PRI | NULL    | auto_increment |
| title         | varchar(255) | YES  |     | NULL    |                |
| after         | int(11)      | YES  |     | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+

现在,我想从表中选择所有行,但是作为已排序的链表。 after是查询结果中应该出现的id行。当然,我可以在使用此表的脚本中查询后执行此操作,但我想知道是否有办法以这种方式对行进行排序。

表格中的数据示例:

(1, "title #1", 0)
(2, "title #2", 3)
(3, "title #3", 1)
(4, "title #4", 2)

预期结果:

(1, "title #1", 0)
(3, "title #3", 1)
(2, "title #2", 3)
(4, "title #4", 2)

6 个答案:

答案 0 :(得分:2)

如果对于所有行,您的after值比id值更小(或更大),则发布的ORDER BY解决方案将会执行。

如果没有,您将需要迭代地遍历after-> id关系,并且原始SQL根本不支持此。现代SQL允许您在SELECT子句中执行此操作,例如Oracle有CONNECT BY,而recursive subqueries也可以。 MySQL显然没有等价物。

另一种方法是在the procedural language you can wrap around SQL queries中进行迭代,就像在the article Skrol29 links to中一样。

然而,无论你如何执行,这次迭代总是很慢。

另一种方法是重新设计您在数据库中表示此关系的方式 - 参见例如nested set model

答案 1 :(得分:1)

你不能在mysql中做这个标准,你可以编写像

这样的东西
Select * from books b_root
   Left join books as b_child1 ON b_root.after = b_child1.id
      Left join books as b_child2 ON b_child1.after = b_child2.id
Where b_root.after = 0

你会得到类似的东西 (1,“标题#1”,0,3,“标题#3”,1,2,“标题#2”,3)

那是3深 或者尝试用脚本或编程语言链接它

解决此问题的python脚本示例

books = [
{'id':1, 'title' :"title #1", 'after':0},
{'id':2, 'title' :"title #2", 'after':3},
{'id':3, 'title' :"title #3", 'after':1},
{'id':4, 'title' :"title #4", 'after':2},]

def recursive(book):
    global books

    for i in books:
        if book['id'] == i['after']:

            print i
            recursive(i)

for i in books:
        if i['after'] == 0:
            print i
            recursive(i)

答案 2 :(得分:1)

SELECT * FROM my_table ORDER BY after;

不起作用。所描述的问题就像一个人的队列,每个人都只知道前面的单身人士。

恕我直言,最好的方法是有一个单独的排序表来表示队列:

> describe books_order;
+---------------+--------------+------+-----+---------+
| Field         | Type         | Null | Key | Default |
+---------------+--------------+------+-----+---------+
| order_no      | int(11)      | NO   |     |         |
| books_id      | int(11)      | NO   |     |         |
+---------------+--------------+------+-----+---------+

SELECT * FROM books WHERE id = (SELECT books_id FROM books_order ORDER BY order_no);

答案 3 :(得分:1)

这实际上是一个分层查询问题。 实际上,您需要对行进行排序,考虑到每行对于父行具有“child_row.after = parent_row.id”的行。

如果您的层次结构只有一个级别,则可以使用简单查询完成。 如果你的层次结构有一个免费的级别,那么解决它是非常困难的,因为MySQL没有分层功能。

但这是一篇解决问题的文章:

http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/

答案 4 :(得分:0)

有这个表:

create table list(id int primary key not null, previous int, description varchar(10));

您可以通过以下方式获取元素:

select l2.* from (select @r as _parent, @r := (select id from list where previous = _parent) as id, @n := @n + 1 as n from (select @r := 0, @n := 0) vars, list) k, list l2 where k.id = l2.id order by n;

答案 5 :(得分:-3)

这应该会给你预期的结果。

SELECT * FROM books ORDER BY after;

访问以下链接了解更多详情: Mysql Select Tutorial