2017-01-18 10 views
1

Materialized Pathを使用して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のsortユーティリティと同じ方法でソートするには?おそらく別の照合や何か?または他のトリックですか?

+0

あなたが '/'とすべてのパスを終わらせることができました。 – Solarflare

答えて

1

これを試してみてください:

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

が生成されます/foo//foo-後に来るので

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

/foo/foo-it後にソートされます。

-の代わりに/の後に来るものを置き換えて、パスやファイル名では許可されていないような気がします。

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

が生成されます

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

これは完璧です、ありがとう! –

関連する問題