2017-01-18 23 views
1

Я использую материализованный путь для хранения древовидной структуры в SQl (MySQL 5.7 в моем случае). Я сохраняю пути в виде слэш-разделенных слизней. Все учебники, которые я прочитал, говорят, чтобы отсортировать строки по пути, чтобы извлечь его в правильном порядке, но он, похоже, не работает, если части пути имеют аналогичный префикс.Как правильно отсортировать материализованные пути в SQL?

Некоторые примеры кода:

CREATE TABLE categories (
    id int(11), 
    parent_id int(11) DEFAULT NULL, 
    slug varchar(255), 
    path varchar(255) 
); 

INSERT INTO categories VALUES 
    (1, null, 'foo', '/foo'), 
    (2, 1, 'bar', '/foo/bar'), 
    (3, null, 'foo-it', '/foo-it'), 
    (4, 3, 'boy', '/foo-it/boy'); 

Теперь, при сортировке по пути я получаю неправильный заказ:

SELECT * FROM categories ORDER BY path; 

Выход:

+------+-----------+--------+-------------+ 
| id | parent_id | slug | path  | 
+------+-----------+--------+-------------+ 
| 1 |  NULL | foo | /foo  | 
| 3 |  NULL | foo-it | /foo-it  | 
| 4 |   3 | boy | /foo-it/boy | 
| 2 |   1 | bar | /foo/bar | 
+------+-----------+--------+-------------+ 
4 rows in set (0.00 sec) 

Это, как представляется, вызвана тем, что - предшествует/в большинстве (всех?) сопоставлений.

Сумасшедшая вещь, утилита командной строки unix sort делает правильную вещь. Если я ставлю все пути в файл и разбирайтесь, я получаю правильный вывод:

$ sort paths.txt 
/foo 
/foo/bar 
/foo-it 
/foo-it/boy 

Есть ли способ, чтобы сделать MySQL сортирует дерево правильно? Чтобы отсортировать его так же, как утилита сортировки unix? Может быть, другая сортировка или что-то еще? Или любые другие трюки?

+0

Вы можете закончить все пути с '/'. – Solarflare

ответ

1

Попробуйте это:

SELECT * FROM categories ORDER BY path + '/'; 

Производит:

/foo-it 
/foo-it/boy 
/foo 
/foo/bar 

/foo сортируется после /foo-it, потому что /foo/ приходит после /foo-.

Вы можете немного поиграть, как замена - на что-то, что приходит после / в порядке и не разрешено в путях или имени файла.

SELECT * FROM categories ORDER BY replace(path,'-','?') + '/'; 

Производит:

/foo 
/foo/bar 
/foo-it 
/foo-it/boy 
+0

Это прекрасно, спасибо! –

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

  • Нет связанных вопросов^_^