Search code examples
mysqlsqlsql-order-byhierarchical-datarecursive-query

MySQL query order items based on next and previous item


I have a table of items created with the following SQL code.

CREATE TABLE `items` (
    `id` INT (11) NOT NULL AUTO_INCREMENT
    ,`Contents` VARCHAR(256) NOT NULL
    ,`Set` INT (11) DEFAULT NULL
    ,`Nxt` INT (11) DEFAULT NULL
    ,`Prev` INT (11) DEFAULT NULL
    ,PRIMARY KEY (`id`)
    ,KEY `Nxt`(`Prev`)
    ,KEY `Prev`(`Nxt`)
    ,CONSTRAINT `items_ibfk_1` FOREIGN KEY (`Nxt`) REFERENCES `items`(`id`)
    ,CONSTRAINT `items_ibfk_2` FOREIGN KEY (`Prev`) REFERENCES `items`(`id`)
    ) ENGINE = InnoDB DEFAULT CHARSET = utf8;

As you can see each item reference it's previous and the next items it's related too and I have the following data in there.

Id      Contents    Set     Prev        Nxt
1       dakhd       1       NULL        4
2       234         2       7           6
3       fwer4w5     1       4           8
4       f34w5       1       1           3
5       234d233     2       NULL        7
6       1234        2       2           NULL
7       324         2       5           2
8       qw4         1       3           NULL

How can I write a query so that I have them ordered by Set, then take the item with NULL in the Prev column then take each of the next items example:

Id      Contents    Set     Prev        Nxt
1       dakhd       1       NULL        4
4       f34w5       1       1           3
3       fwer4w5     1       4           8
8       qw4         1       3           NULL
5       234d233     2       NULL        7
7       324         2       5           2
2       234         2       7           6
6       1234        2       2           NULL

I have the following query which will sort them by. the Set column however I'm not sure where to start with the ordering of the items

select * from `items` order by `Set`;

Solution

  • You could work with case when, assuming that id is always greater 0 the following should work:

    select * 
    from `items` 
    order by `Set`
    ,case when `Prev` is null then -1 when `Nxt` is null then 1000000 else `Nxt` end
    ;