Сортировка MySQL по 2 колонкам - PullRequest
0 голосов
/ 08 июля 2011

Я пытаюсь создать своего рода систему меню со следующей структурой и соответствующим образом отсортировать содержимое.

+----+-------+----------+
| id | title | parentid |
+----+-------+----------+
| 1  | a     | 0        |
| 2  | b     | 0        |
| 3  | c     | 0        |
| 4  | aa    | 1        |
| 5  | ab    | 1        |
| 6  | ca    | 3        |
+----+-------+----------+

Я хотел бы отсортировать их, как показано ниже, однако я не могу найти или найтис объединением или сортировкой по запросу, который будет работать.

+----+-------+----------+
| id | title | parentid |
+----+-------+----------+
| 1  | a     | 0        |
| 4  | aa    | 1        |
| 5  | ab    | 1        |
| 2  | b     | 0        |
| 3  | c     | 0        |
| 6  | ca    | 3        |
+----+-------+----------+

1 Ответ

1 голос
/ 08 июля 2011

Я думаю, что вы на самом деле просите упорядочить свое дерево по родительскому идентификатору.

Это довольно сложная вещь, хотя мы делаем это на работе, поэтому я покажу вам, чтомы делаем.Хотя мы используем PostgreSQL, вам, несомненно, придется адаптировать его к MySQL.Но, надеюсь, это укажет вам правильное направление.

Мы используем эту структуру данных для нашей uids table "

                          Table "public.uids"
   Column   |            Type             |              Modifiers
------------+-----------------------------+-----------------------------
 uid        | integer                     | not null default 
 name       | character varying(64)       | not null
 parent     | integer                     |

И у нас есть вспомогательная таблица, которую мык сожалению, вызовите uid_cache , который выглядит следующим образом:

          Table "public.uid_cache"
 Column |   Type   | Modifiers | Description 
--------+----------+-----------+-------------
 uid    | integer  | not null  | 
 parent | integer  | not null  | 
 level  | smallint | not null  | 

Эта таблица обновляется с помощью триггеров INSERT / UPDATE / DELETE на основных uids Таблица. Триггер делает много других вещей, которые очень специфичны для нашего приложения, и он длинный и громоздкий, поэтому я не буду публиковать его здесь. Но эта вспомогательная таблица содержит одну строку для каждого отношения uid / parent, которое существует в системе,и level показывает, сколько шагов между ними.

Так, например, если наша таблица uids содержит:

 uid | parent 
-----+--------
   0 |       
   1 |      0
   2 |      1
   3 |      1

(uid0 не имеет родителя, это основной родительский uid

Тогда наша таблица uid_cache содержит:

 uid | parent | level 
-----+--------+-------
   0 |      0 |     0
   1 |      1 |     0
   1 |      0 |     1
   2 |      2 |     0
   2 |      1 |     1
   2 |      0 |     2
   3 |      3 |     0
   3 |      1 |     1
   3 |      0 |     2
(8 rows)

С этой таблицей этолегко определить с первого взгляда «расстояние» между любыми двумя uids.ом это родитель 0 это 2 шага.3 расстояние от его родителя 1 составляет 1 шаг.И расстояние 3 от себя, ну, 0 шагов.(Вы можете или не можете записывать отношения uid с самим собой, в зависимости от вашего приложения - это полезно в нашем случае)

Теперь, с помощью этих двух таблиц, мы можем создать эту хранимую процедуру:

CREATE OR REPLACE FUNCTION uid_tree(INTEGER) RETURNS INTEGER[] AS $$
    SELECT ARRAY(SELECT parent FROM uid_cache WHERE uid = $1 ORDER BY level DESC)
$$ LANGUAGE SQL STABLE STRICT;

Затем с помощью этой функции мы можем сделать:

SELECT uid,parent,uid_tree(uid)
FROM uids
ORDER BY uid_tree(uid);

И мы получим:

 uid | parent | uid_tree 
-----+--------+----------
   0 |        | {0}
   1 |      0 | {0,1}
   2 |      1 | {0,1,2}
   3 |      1 | {0,1,3}
(4 rows)

Я почти уверен, что это ответ, который вы ищете,У меня также есть большое подозрение, что это гораздо больше, чем вы надеялись!

Пожалуйста, дайте мне знать, если я смогу что-то уточнить для вас.

...