1
CREATE TABLE sectors
(
    sector_id integer PRIMARY KEY,
    sector_name varchar(100) NOT NULL,
    parent_sector_id integer REFERENCES sectors(sector_id)
);

INSERT INTO sectors(sector_id, sector_name, parent_sector_id)
SELECT 1, 'All sectors', NULL UNION ALL
SELECT 2, 'Business', 1 UNION ALL
SELECT 3, 'Manufacturing', 2 UNION ALL
SELECT 4, 'Retail', 2 UNION ALL
SELECT 5, 'Trading', 1 UNION ALL
SELECT 6, 'Nonprofit', 1 UNION ALL
SELECT 7, 'Agriculture', 1;

質問1:関数を介して親の関係を見つける

SELECT is_parent(1/*All sectors*/, 4/*Retail*/) should be true
SELECT is_parent(2/*Business*/, 4/*Retail*/) should be true

質問2:関数を介して子供の関係を見つける

SELECT is_child(4/*Retail*/, 1/*All sectors*/) should be true
SELECT is_child(4/*Retail*/, 2/*Business*/) should be true

これに関する助けをいただければ幸いです。

4

2 に答える 2

3

そのようなクエリに本当に答える必要がある場合は、PostgreSQLの再帰クエリを確認することをお勧めします。is_parentこれらの関数( 、 )を実際に作成する必要があるある種の宿題の場合は、is_child再帰クエリを使用してそれらを実装することもお勧めします。

于 2011-06-26T15:28:58.840 に答える
2

パブロの応答に追加...

再帰クエリを使用is_parent()すると、非常に高速になります。にインデックスがあると仮定すると、parent_sector_id基本的に深度レベルごとに1つのインデックススキャンを実行します。

is_child()対照的に、単純な方法で実装し、巨大なツリーがある場合は、非常に遅くなります。つまり、すべての子を取得してノードをチェックするわけではありません。

そのようなツリーがあり、ときどきすべての子を取得する必要がある場合、1つの良いオプションは、事前に順序付けられたツリーアルゴリズム(浮動小数点数または数値を使用します。整数ではなく、書き込みが大幅に遅くなるため)またはネストされた間隔を実装することです。

そうでない場合は、引数を逆にして呼び出すだけです。is_parent()つまり、sql関数is_child(a, b)はを返しis_parent(b, a)ます。

最後になりましたが、contribのltreeデータ型を調べてみてください。これを使用すると、任意のノードで要点インデックスを使用してis_parent/is_childクエリを実行できます。

于 2011-06-26T20:13:10.833 に答える