2012-04-18 44 views
1

具有例如2個表:排序對象關係(PostgreSQL的)

在第一:對象&父列

object | parent 
-------+--------- 
object1| null  
object2| object1 
object3| null 

第二有:對象&參考列

object | reference 
-------+--------- 
object1| null  
object2| null  
object3| object1  

需要按照以下順序查詢表格:pa租金是第一位的,然後是 - 孩子,是對父母有參考意義的對象。

object1 
object2 
object3 

是否可以在一個SQL查詢中執行或需要在數組中手動​​排序?看起來這是一個經典的任務,可能解決方案已經存在某處?

+0

完全困惑....你有兩個表的對象,在這兩個表中的父?是第一個表引用第二個表,還是你有一個表爲每個對象/父對(希望​​不是後者,因爲它很奇怪)。 – Twelfth 2012-04-18 21:57:26

+0

對不起,固定的列名。 – 2012-04-18 22:08:18

+0

恐怕即使進行了更正,我也不太明白這個問題。你能否詳細說明表格之間的關係? – kgrittn 2012-04-18 22:32:06

回答

0

下面的遞歸查詢的工作:

WITH RECURSIVE tables(object, rank) AS (
    SELECT DISTINCT o.object, 1 AS rank FROM oref o 
    WHERE o.ref IS NULL 
    UNION 
    SELECT o.object, t.rank + 1 AS rank 
    FROM (SELECT DISTINCT o.object, o.ref FROM oref o 
      WHERE ref IS NOT NULL) o, tables t 
    WHERE o.ref = t.object AND rank <= t.rank 
), 
ordered AS (
    SELECT * FROM tables 
) 
SELECT * FROM tables 
WHERE tables.rank = (SELECT MAX(rank) FROM ordered WHERE ordered.object = tables.object) 
ORDER BY rank; 

任何意見,問題,反對,主張? ;)

1

這是你在找什麼?

CREATE TABLE oparen (object varchar(10), parent varchar(10)); 
CREATE TABLE oref (object varchar(10), ref varchar(10)); 
INSERT INTO oparen VALUES 
    ('object1',null),('object2','object1'), 
    ('object3',null),('object4','object2'); 
INSERT INTO oref VALUES 
    ('object1',null),('object2',null),('object3','object1'), 
    ('object5','object6'),('object6','object1'),('object7','object4'); 

WITH hier AS (
    SELECT parent AS obj, 1 AS rank FROM oparen 
    WHERE parent IS NOT NULL 
    UNION 
    SELECT object, 2 FROM oparen 
    WHERE parent IS NOT NULL 
    UNION 
    SELECT object, 3 FROM oref 
    WHERE ref IS NOT NULL), 
allobj AS (
    SELECT object AS obj FROM oparen 
    UNION 
    SELECT object FROM oref) 
SELECT a.obj, coalesce(h.rank, 4) AS rank 
    FROM allobj a LEFT JOIN hier h ON a.obj = h.obj 
ORDER BY coalesce(h.rank, 4), a.obj; 

編輯:在下面的答案改進的例子之後,下面的查詢應該做的伎倆:在上面

WITH parents AS (
    SELECT parent AS obj, 1 AS rank FROM oparen 
    WHERE parent IS NOT NULL 
    ), 
family AS (
    SELECT * FROM parents 
    UNION ALL 
    SELECT object, 2 FROM oparen op 
    WHERE parent IS NOT NULL 
     AND NOT EXISTS (SELECT obj FROM parents WHERE obj = op.object) 
    ), 
hier AS (
    SELECT * FROM family 
    UNION ALL 
    SELECT object AS obj, coalesce(f.rank + 2, 5) AS rank 
     FROM oref LEFT JOIN family f ON oref.ref = f.obj 
    WHERE ref IS NOT NULL 
    ), 
allobj AS (
    SELECT object AS obj FROM oparen 
    UNION 
    SELECT object FROM oref) 
SELECT a.obj, h.rank AS rank 
    FROM allobj a LEFT JOIN hier h ON a.obj = h.obj 
ORDER BY h.rank, a.obj; 

測試平臺創建根據新的要求進行更新。

+0

+1這應該做到這一點。考慮第一個CTE的'UNION ALL'。 – 2012-04-19 15:06:06

+0

工作不正常,請參閱下面的答案。 – 2012-04-20 06:44:19

0

我插入以下數據:

INSERT INTO oparen VALUES 
    ('object1',null),('object2','object1'),('object3',null),('object4','object2'); 
INSERT INTO oref VALUES 
    ('object1',null),('object2',null),('object3','object1'),('object5','object6'),('object6','object1'); 

順序不正確和對象2列出了兩次。對obj的DISTINCT也會破壞順序。應該去6然後5.

+0

非常好。我們最初的投入越多,SO社區越容易爲您提供正確的答案。 – vyegorov 2012-04-20 07:50:09

0

不,不工作:檢查另一個數據和簡化僅OREF表的內容使用和:

INSERT INTO oref VALUES 
('object1',null),('object2',null),('object3','object1'), 
('object5','object6'),('object6','object1'),('object7','object4'), ('object4','object5'); 

WITH family AS (
    SELECT object AS obj, 1 AS rank FROM oref 
    WHERE ref IS NULL 
    ), 
hier AS (
    SELECT * FROM family 
    UNION ALL 
    SELECT object AS obj, coalesce(f.rank + 2, 5) AS rank 
     FROM oref LEFT JOIN family f ON oref.ref = f.obj 
    WHERE ref IS NOT NULL 
    ), 
allobj AS (
    SELECT object AS obj FROM oref) 
SELECT a.obj, h.rank AS rank 
    FROM allobj a 
    LEFT JOIN hier h ON a.obj = h.obj 
ORDER BY h.rank, a.obj; 

想到這裏需要使用遞歸查詢。將寫在這裏並張貼。