2

ページのリストからナビゲーション メニューを作成しています。テーブルは次のようになります。

Table name: pages

id | type | parent | name
-------------------------------
1,    1,     null,   root1
2,    1,     null,   root2
3,    2,     2,      home
4,    2,     3,      child
5,    2,     4,      sub_child
6,    3,     5,      sub_sub_child


type:
1 = root page / site
2 = page
3 = ...

私の問題は、どのページからでもルートページを見つけなければならないことです。ルート ページを除いて、親ページを参照する列の親があります。

テーブルには複数のルート ページを含めることができますが、各ページには親が 1 つしかありません。

誰かが再帰クエリを書くのを手伝ってくれませんか?

このクエリを使用しようとしていますが、機能しません:

with recursive pages (id, parent) as 
(
    select pages.id, 
    pages.parent, 
    from pages
    where pages.id = 4

union all
    select pages.id, 
    pages.parent,
    from pages
    inner join pages p on p.id = pages.parent
)
select id
from pages;

ありがとう

4

4 に答える 4

1

データベース内のツリー構造化データを処理するための私のfaroviteのトリックは、FullID複雑な(おそらく再帰的な)SQL/ストアドプロシージャを回避するためにテーブルに列を追加することです。

FullID     id  parent   name
-----------------------------
1          1   null     root1
2          2   null     root2
2.3        3   2        home
2.3.4      4   3        child
2.3.4.5    5   4        sub_child
2.3.4.5.6  6   5        sub_sub_child

したがって、ルートページIDを見つけるには、FullIDSQLまたはアプリケーション言語を介しての最初の部分を抽出するだけです。

SQLを使用している場合は、次のSQLを使用してルートIDを取得できます。

-- MySQL dialect
select substring_index(FullID,'.',1) as RootID from table;

-- SQL Server dialect
select case charindex('.', FullID) when 0 then FullID else substring(FullID, 1, charindex('.', FullID)-1) end as RootID from table

ノードとその子を削除するには

DELETE table WHERE id=<CURRENT_NODE_ID> OR FullID LIKE '<CURREN_NODE_FULLID>.%'

ノードとその子を移動するには

-- change the parent of current node:
UPDATE table
SET parent=<NEW_PARENT_ID>
WHERE id=<CURRENT_NODE_ID>

-- update it's FullID and all children's FullID:
UPDATE table
SET FullID=REPLACE(FullID,<CURRENT_NODE_PARENT_FULLID>, <NEW_PARENT_FULLID>)
WHERE (id=<CURRENT_NODE_ID> OR FullID LIKE '<CURRENT_NODE_FULLID>.%')

ノート

このトリックは、限られたツリーレベルの場合にのみ適用されます。または、FullIDツリーレベルが深すぎる場合、長いコンテンツを保持できません。

于 2012-06-20T12:12:43.390 に答える
1

他の投稿者がコメントしているように、MySQLではこれがサポートされていないようです。ネストされたセットモデルを使用してテーブルを再構築し、階層クエリの必要性をなくすことができます。

parent列の代わりに、、、がleftidありrightidますis_root

id | type | leftid | rightid | is_root |  name
------------------------------------------------
1,    1,     1,      2         1          root1
2,    1,     3,      12        1          root2
3,    2,     4,      11        0          home
4,    2,     5,      10        0          child
5,    2,     6,      9         0          sub_child
6,    3,     7,      8         0          sub_sub_child

次に、特定のレコードの親を見つけるには、そのレコードよりもleftid小さいレコードとrightid大きいレコードを検索します。列を使用してis_root、最終的なルートレコードを取得します。

于 2012-06-20T11:58:12.600 に答える
0

データベースにいくつかの変更を加えると思います。話した後、列タイプを削除し、さまざまなページを分類するためのテーブルを追加できます。そのため、構造が変更されます。PHPループを使用すると思います。美しくはありませんが、機能し、遅すぎることはありません...下に200人の子供がいることは決してありません...しかし、私は覚えていSTART WITHます。

君たちありがとう

于 2012-06-20T13:09:18.810 に答える
0

使用WITH RECURSIVEしている句は、MySQLではなくPostgreSQLデータベースに適用されます。OracleにはそれがCONNECT BY ... START WITH ...あり、再帰クエリはデータベースごとに異なる方法で実行されるようです。

ただし、MySQLは再帰/階層クエリをサポートしていません。ルートまでの親を見つけるには、行を手続き的にループする必要があります。

階層クエリ(OracleのようなCONNECT BY)をMySQLでエミュレートする方法をご覧ください。

于 2012-06-20T11:53:47.550 に答える