MySQL ネストされたセット - ノードの親を見つけるには?
-
05-07-2019 - |
質問
次の列を使用して、ネストされたセットの階層タイプをセットアップします。
テーブル名:
myset
列:
id, name, lft, rgt
を判断するためのクエリを知っている人はいますか 親 ノードの?
いくつかの場所で読んだのですが、 親ID これを追跡するためにテーブル内の列を追加しますが、これは冗長であり、セット内で何かを追加/削除/移動するときにクエリが誤って実行された場合、ネストされたセットとの同期が失われる可能性があるようです。
解決
この質問。それはあなたのものに似ています。必要なクエリを投稿しました。
SELECT title, (SELECT TOP 1 title
FROM tree t2
WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt
ORDER BY t2.rgt-t1.rgt ASC) AS parent
FROM tree t1
ORDER BY rgt-lft DESC
必要なものがあることを願っています。
次の表の場合:
+-------------+----------------------+-----+-----+
| category_id | name | lft | rgt |
+-------------+----------------------+-----+-----+
| 1 | ELECTRONICS | 1 | 20 |
| 2 | TELEVISIONS | 2 | 9 |
| 3 | TUBE | 3 | 4 |
| 4 | LCD | 5 | 6 |
| 5 | PLASMA | 7 | 8 |
| 6 | PORTABLE ELECTRONICS | 10 | 19 |
| 7 | MP3 PLAYERS | 11 | 14 |
| 8 | FLASH | 12 | 13 |
| 9 | CD PLAYERS | 15 | 16 |
| 10 | 2 WAY RADIOS | 17 | 18 |
出力が生成されます:
title | parent
----------------------------------------------
ELECTRONICS | NULL
PORTABLE ELECTRONICS | ELECTRONICS
TELEVISIONS | ELECTRONICS
MP3 PLAYERS | PORTABLE ELECTRONICS
FLASH | MP3 PLAYERS
CD PLAYERS | PORTABLE ELECTRONICS
2 WAY RADIOS | PORTABLE ELECTRONICS
TUBE | TELEVISIONS
LCD | TELEVISIONS
PLASMA | TELEVISIONS
他のヒント
TOPはMSSQLコマンドです。MySQLにはLIMITを使用します:
SELECT title, (SELECT title
FROM tree t2
WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt
ORDER BY t2.rgt-t1.rgt ASC
LIMIT 1)
AS parent FROM tree t1
ORDER BY (rgt-lft) DESC
トリックを行う必要があります..
私を大いに助けてくれたこれらの回答に追加するだけで、
ノードの直接の親と、場合によってはノード チェーンの最上位の親を見つける必要がありました。
私は子から親の順序で項目を取得するために以下をベースとして使用しました
SELECT parent.* FROM
nested_set node,
nested_set parent
WHERE (
node.set_left BETWEEN parent.set_left AND parent.set_right
)
AND node.set_id={CHILD_NODE_ID_HERE}
ORDER BY parent.set_right - parent.set_left
#LIMIT 1,1
あとは、 LIMIT 1,1
直接の親となる 2 行目のみをキャプチャする
また、上記のクエリでは、ノード自体が最上位の親である場合、ノードには 直属の親, 、それで、 LIMIT 1,1
空の結果セットを返す必要があります
最上位の親を取得するために、order by 句を逆にして、ノード自体が最上位の親であるかどうかのチェックを含め、結果を最初の行に制限しました。
SELECT parent.* AS top_level_right FROM
nested_set node,
nested_set parent
WHERE (
node.set_left >= parent.set_left
AND node.set_left <= parent.set_right
)
AND node.set_id={CHILD_NODE_ID_HERE}
ORDER BY parent.set_left - parent.set_right
LIMIT 1
最後に使用したクエリで >= <=
子ノードがトップレベルの親である場合に、選択した範囲が子ノードを包含するように演算子を追加します。
Lucaszのクエリに問題がありました。私のバージョンのmysqlはTOPコマンドを理解しませんでした。代わりにLIMITを使用する必要がありました。修正されたコードは次のとおりです。
SELECT
`id`,
(SELECT
`id`
FROM
`[*** YOUR TABLE ***]` AS `t2`
WHERE
`t2`.`left_id` < `t1`.`left_id`AND
`t2`.`right_id` > `t1`.`right_id`
ORDER BY
`t2`.`right_id`-`t1`.`right_id`ASC
LIMIT
1) AS `parent`
FROM
`[*** YOUR TABLE ***]` AS `t1`
WHERE
`t1`.`id` = [*** ID OF THE NODE WHOS PARENT YOU WISH TO LOOKUP ***]
ORDER BY
`right_id`-`left_id` DESC
明らかに、ニーズに合わせて[]の内容を変更してください。 []も削除します。このクエリは1行のみを返します。そのように...
id parent
7 3
select * from myset
where lft < :lftOfCurrent and rgt > :lftOfCurrent
order lft desc
limit 1
order / limitではなくmaxを使用できます。データベースに応じて、結果を1行に制限する別のキーワードが必要になる場合があります。 <!> ltではなく間および<!> gt;データベースが排他セットを返す場合は機能しますが、MySQLはそうしません。
SELECT parent.name
FROM myset AS node, myset AS parent
WHERE parent.lft < node.lft
AND parent.rgt > node.rgt
AND node.id = {YOUR CATEGORY ID}
ORDER BY ( parent.rgt - parent.lft ) ASC LIMIT 1;
すべての祖先は以下によって返されます
SELECT id FROM thetable
WHERE x BETWEEN lft and rgt;
つまり、直接の親はlftとrgtの差が最も小さい祖先です。
SELECT id FROM thetable
WHERE x BETWEEN lft and rgt
ORDER BY (rgt-lft)
LIMIT 1
spankmaster79のコードは完全に間違っていたわけではありません。私は彼のコードを修正し、機能しました。
SELECT parent . * FROM Nested_Category AS node, Nested_Category AS parent
enter code hereWHERE node.leftSide
BETWEEN parent.leftSide
AND parent.rightSide
AND node.id ='Enter the Node ID'
ORDER BY (
parent.rightSide - parent.leftSide
)
LIMIT 1 , 1