2013-10-01 3 views
12

SO,Reverse присоединиться к MySQL

Проблема

Мой вопрос о - как соединить таблицу в MySQL с собой в обратном порядке? Предположим, что у меня есть:

 
id name 
1 First 
2 Second 
5 Third 
6 Fourth 
7 Fifth 
8 Sixth 
9 Seventh 
13 Eight 
14 Nine 
15 Tenth 

-И теперь я хочу, чтобы создать запрос, который будет возвращать присоединившихся записи в обратном порядке:

 
left_id name right_id name 
    1 First  15 Tenth 
    2 Second  14 Nine 
    5 Third  13 Eight 
    6 Fourth  9 Seventh 
    7 Fifth  8 Sixth 
    8 Sixth  7 Fifth 
    9 Seventh  6 Fourth 
    13 Eight  5 Third 
    14 Nine  2 Second 
    15 Tenth  1 First 

Мой подход

я сейчас этот запрос :

SELECT 
    l.id AS left_id, 
    l.name, 
    (SELECT COUNT(1) FROM sequences WHERE id<=left_id) AS left_order, 
    r.id AS right_id, 
    r.name, 
    (SELECT COUNT(1) FROM sequences WHERE id<=right_id) AS right_order 
FROM 
    sequences AS l 
    LEFT JOIN 
    sequences AS r ON 1 
HAVING 
    left_order+right_order=(1+(SELECT COUNT(1) FROM sequences)); 

-Всего этого fiddle для структуры образца & код.

Некоторые фон

Там нет случай использования для этого. Раньше я делал это в приложении. Теперь в основном любопытство, если есть способ сделать это в SQL - вот почему я ищу не просто «какое-либо решение» (например, мое), но как можно более простое решение. Исходная таблица всегда будет маленькой (< 10.000 записей) - так что производительность не вещь, чтобы заботиться, я думаю.

Вопрос

Может ли мой запрос быть упрощена так или иначе? Кроме того, важно не использовать переменные. Заказ может быть включен в результат (как в моей скрипке) - но это не обязательно.

+0

Хотя мы думаем - не могли бы вы предоставить прецедент для этого?Любопытно – zerkms

+0

@zerkms Я обновил –

+0

Думаю, вы ограничены MySQL? В противном случае было бы легко использовать функции окна. –

ответ

2

Единственное, что я могу думать, чтобы улучшить это

SELECT 
    l.id AS left_id, 
    l.name ln, 
    (SELECT COUNT(1) FROM sequences WHERE id<=left_id) AS left_order, 
    r.id AS right_id, 
    r.name rn, 
    (SELECT COUNT(1) FROM sequences WHERE id>=right_id) AS right_order 
FROM 
    sequences AS l 
    LEFT JOIN 
    sequences AS r ON 1 
HAVING 
    left_order=right_order; 

Есть 2 изменений, которые должны сделать это немного быстрее:

1) Расчет правильный порядок в обратном порядке, в первую очередь

2) избегайте использования SELECT COUNT в последней строке.

Edit: я псевдонимами ЛУ, гп, потому что я не мог видеть столбцы в скрипку

+0

Это выглядит интересно, спасибо, я проведу –

0
SET @rank1=0; 
SET @rank2=0; 

SELECT * 
FROM (SELECT *, @rank1 := @rank1 + 1 AS row_number FROM sequences ORDER BY ID ASC) t1 
INNER JOIN (SELECT *, @rank2 := @rank2 + 1 AS row_number FROM sequences ORDER BY ID DESC) t2 
on t1.row_number = t2.row_number 

По какой-то причине sql fiddler для этого отображает только 3 столбца, не уверенный, что мой запрос плох.

+0

Я не хочу использовать переменные (из-за соображений переносимости) - так что это не то, m ищет –

+0

ouch, должен научиться читать 8 ( – athabaska

1

Без SQL standard RANK() OVER(...), вы должны вычислить заказ, как вы сами обнаружили.

RANK() строки - это просто 1 + COUNT() всех строк с лучшим рангом. (DENSE_RANK() для сравнения - 1 + COUNT() всех DISTINCT лучших рангов.) Хотя RANK() можно вычислить как скалярный подзапрос в вашей проекции SELECT, как, например, вы сделали с SELECT (SELECT COUNT(1) ...), ... - я склонен предпочтительнее:

SELECT lft.id AS "left_id", lft.name AS "left_name", 
      rgt.id AS "right_id", rgt.name AS "right_name" 
     FROM ( SELECT s.id, s.name, COUNT(1) AS "rank"  -- Left ranking 
       FROM sequences s 
      LEFT JOIN sequences d ON s.id <= d.id 
      GROUP BY 1, 2) lft 
INNER JOIN ( SELECT s.id, s.name, COUNT(1) AS "rank"  -- Right ranking 
       FROM sequences s 
      LEFT JOIN sequences d ON s.id >= d.id 
      GROUP BY 1, 2) rgt 
      ON lft.rank = rgt.rank 
    ORDER BY lft.id ASC; 
+0

Это также хорошо выглядит с 'JOIN' (на самом деле, я предпочитаю' JOIN', а не подзапросы) –

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