2011-06-26 30 views
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:查找通過功能父關係PostgreSQL的層次關係功能

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 

任何幫助將是高度讚賞。

回答

2

添加到Pablo的響應...

使用遞歸查詢,is_parent()將是非常快。假設你有一個在parent_sector_id上的索引,你將基本上對每個深度級別進行一次索引掃描。

is_child()相比之下,如果你以一種天真的方式實現它,並且擁有一棵巨大的樹,也就是說不要抓住所有的孩子並檢查你的節點,它將會非常緩慢。

如果你有這樣一棵樹,偶爾需要檢索所有的孩子,一個好的選擇是實現一個預定義的樹算法(使用浮點數或數字;不是整數,因爲它們極大地減慢了寫入)或嵌套間隔。

如果不是,則只需顛倒參數並調用is_parent(),即sql函數is_child(a, b)將返回is_parent(b, a)

最後但並非最不重要的一點,你可能想看看是在contrib中的ltree datatype。使用它,您可以在任意節點上執行帶有索引的is_parent/is_child查詢。

+0

+1有關ltree數據類型的信息。可悲的是,我不能在這裏使用它。謝謝denis。 :) –

3

如果你確實需要回答這種查詢,我建議你看看PostgreSQL's recursive queries。如果是某種需要實際編寫這些功能的作業(is_parent,is_child),我還建議您使用遞歸查詢來實現它們。