2013-04-04 3 views
3

У меня есть простая таблица под название пользователей со следующими данными:Следующие и предыдущие записей в MySQL после сортировки DESC

id | hops 
1 | 3 
2 | 1 
3 | 5 
4 | 2 
5 | 6 
6 | 5 

Я хочу сделать предыдущую/следующую навигацию в соответствии с хмелем, отсортированным по убыванию. Я использую следующие для запроса сортировать по убыванию:

SELECT * FROM users ORDER BY hops DESC, id DESC 

Это результат:

id | hops 
5 | 6 
6 | 5 
3 | 5 
1 | 3 
4 | 2 
2 | 1 

Теперь то, что я хочу, что когда я ввести любой идентификатор в запросе тузд я получаю предыдущий и следующий ids в соответствии с сортировкой выше. Например:

Для получения идентификатора 5 (в данном случае ID = 5 имеет самый высокий хмель так что никаких предыдущие записи перед ним):

id (current) | hops (current) | id (prev) | hops (prev) | id (next) | hops (next) 
    5   | 6   | NULL  | NULL  | 6  | 5 

Для ID 6:

id (current) | hops (current) | id (prev) | hops (prev) | id (next) | hops (next) 
    6   | 5   | 5  |  6  | 3  | 5 

Для получения идентификатора 3 :

id (current) | hops (current) | id (prev) | hops (prev) | id (next) | hops (next) 
    3   | 5   | 6  | 5  | 1  | 3 

Для ид 1:

id (current) | hops (current) | id (prev) | hops (prev) | id (next) | hops (next) 
    1   | 3   | 3  | 5  | 4  | 2 

Для ид 4:

id (current) | hops (current) | id (prev) | hops (prev) | id (next) | hops (next) 
    4   | 2   | 1  | 3   | 2  | 1 

Для идентификатора 2 (в данном случае ид = 2 имеет самый низкий хмель поэтому никаких последующих записей после него)

id (current) | hops (current) | id (prev) | hops (prev) | id (next) | hops (next) 
    2   | 1   | 4  | 2   | NULL  | NULL 

Благодарности

+0

где 7 в вашем столе? –

+0

извините ... это была ошибка :) –

ответ

2

Try:

select cp.*, n.id id_next, n.hops hops_next 
from 
(select c.id id_current, c.hops hops_current, p.id id_previous, p.hops hops_previous 
from 
(select * from users where id = ?) c 
left join users p on c.hops < p.hops or (c.id < p.id and c.hops = p.hops) 
order by p.hops, p.id limit 1) cp 
left join users n 
     on cp.hops_current > n.hops or (cp.id_current > n.id and cp.hops_current = n.hops) 
order by n.hops desc, n.id desc limit 1 

(SQLFiddle here)

2

Это самая странная таблица пользователей, которую я видел до сих пор. Во всяком случае, вот один из способов (хотя я должен признать, что это немного сложно) ...

DROP TABLE IF EXISTS test; 

CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,hops INT NOT NULL); 

INSERT INTO test VALUES 
(1 ,3),(2 ,1),(3,5),(4 ,2),(5 ,6),(6 ,5); 

SELECT c.id id_curr 
    , c.hops hops_curr 
    , p.id id_prev 
    , p.hops hops_prev 
    , n.id id_next 
    , n.hops hops_next 
    FROM 
    (
     SELECT a.* 
      , COUNT(*) new_rank 
     FROM 
      (SELECT x.* 
        , COUNT(*) rank 
       FROM test x 
       JOIN test y 
        ON y.hops >= x.hops 
       GROUP 
        BY x.id 
      ) a 
     JOIN 
      (SELECT x.* 
        , COUNT(*) rank 
       FROM test x 
       JOIN test y 
        ON y.hops >= x.hops 
       GROUP 
        BY x.id 
      ) b 
      ON b.rank < a.rank 
      OR (b.rank = a.rank AND b.id >= a.id) 
     GROUP 
      BY a.id 
    )c 
    LEFT 
    JOIN 
    (
     SELECT a.* 
      , COUNT(*) new_rank 
     FROM 
      (SELECT x.* 
        , COUNT(*) rank 
       FROM test x 
       JOIN test y 
        ON y.hops >= x.hops 
       GROUP 
        BY x.id 
      ) a 
     JOIN 
      (SELECT x.* 
        , COUNT(*) rank 
       FROM test x 
       JOIN test y 
        ON y.hops >= x.hops 
       GROUP 
        BY x.id 
      ) b 
      ON b.rank < a.rank 
      OR (b.rank = a.rank AND b.id >= a.id) 
     GROUP 
      BY a.id 
    ) p 
    ON p.new_rank = c.new_rank-1 
    LEFT 
    JOIN 
    (
     SELECT a.* 
      , COUNT(*) new_rank 
     FROM 
      (SELECT x.* 
        , COUNT(*) rank 
       FROM test x 
       JOIN test y 
        ON y.hops >= x.hops 
       GROUP 
        BY x.id 
      ) a 
     JOIN 
      (SELECT x.* 
        , COUNT(*) rank 
       FROM test x 
       JOIN test y 
        ON y.hops >= x.hops 
       GROUP 
        BY x.id 
      ) b 
      ON b.rank < a.rank 
      OR (b.rank = a.rank AND b.id >= a.id) 
     GROUP 
      BY a.id 
    ) n 
    ON n.new_rank = c.new_rank+1 
ORDER 
    BY c.hops DESC 
    , c.id DESC; 
+0

Лучшая идея с вставкой нового идентификатора столбца id автозагрузки –

+0

Спасибо за ваши усилия, но другое решение кажется мне более прямым, поэтому мне придется выбирать его :) –

+0

Я бы подумал, что факт что этот запрос возвращает все результаты, а не только один будет clincher - но эй, что я знаю ;-) – Strawberry

Смежные вопросы