2017-04-26 76 views
0

這是非常奇怪的查詢,我不知道如何處理它。 以下是表格。如何爲下表編寫postgres查詢?

id descendentId attr_type attr_value 
1 {4}    type_a  
2 {5}    type_a  
3 {6}    type_a  
4 {7,8}    type_b  
5 {9,10}   type_b  
6 {11,12}   type_b  
7 {}    type_x TRUE 
8 {}    type_y "ABC" 
9 {}    type_x FALSE 
10 {}    type_y "PQR" 
11 {}    type_x FALSE 
12 {}    type_y "XYZ" 

輸入相關的查詢將是1,2,3 ..輸出應該"ABC"

邏輯是 - 從1,2,3開始通過後代ID循環,直到達到attr_type x。如果attr_type x達到了7,9和11,那麼檢查哪一個是true。對於例如7是真的,那麼 得到它的兄弟type_y(檢查第4行),這是8並返回它的值。

所有這些都是字符串格式。

+0

'descendentId'的數據類型是什麼? –

+0

如果你保存一個'parentId'而不是這樣(這樣,你甚至可以使用一個自引用外鍵)。 – pozs

回答

0

這可以用recursive CTEs解決:

with recursive params(id) as (
    select e::int 
    from unnest(string_to_array('1,2,3', ',')) e -- input parameter 
), 
rcte as (
    select '{}'::int[] parents, 
      id, 
      descendent_id, 
      attr_type, 
      attr_value 
    from attrs 
    join params using (id) 
    union all 
    select  parents || rcte.id, 
       attrs.id, 
       attrs.descendent_id, 
       attrs.attr_type, 
       attrs.attr_value 
    from  rcte 
    cross join unnest(descendent_id) d 
    join  attrs on attrs.id = d 
    where  d <> all (parents) -- stop at loops in hierarchy 
) 
select y.attr_value 
from rcte x 
join rcte y using (parents) -- join siblings 
where x.attr_type = 'type_x' 
and x.attr_value = 'true' 
and y.attr_type = 'type_y' 

http://rextester.com/YDLDH11322

+0

太好了。我會測試它並讓你知道。 – user1298426

1

這的確是這樣的查詢複雜的數據模型,但我的方式就是擊敗了層次第一:

WITH RECURSIVE 
    typex(id, use) AS (
     SELECT id, attr_value::boolean 
     FROM weird 
     WHERE attr_type = 'type_x' 
     UNION 
     SELECT w.id, typex.use 
     FROM weird w 
      JOIN typex 
       ON ARRAY[typex.id] <@ w.descendentid 
    ), 
    typey(id, value) AS (
     SELECT id, attr_value 
     FROM weird 
     WHERE attr_type = 'type_y' 
     UNION 
     SELECT w.id, typey.value 
     FROM weird w 
      JOIN typey 
       ON ARRAY[typey.id] <@ w.descendentid 
    ) 
SELECT id, value 
FROM typex 
    NATURAL JOIN typey 
WHERE use 
    AND id = 1; 

┌────┬───────┐ 
│ id │ value │ 
├────┼───────┤ 
│ 1 │ ABC │ 
└────┴───────┘ 
(1 row) 
+0

你已經明確提到WHERE使用AND ID = 1;所以如果9是真的,7是假的,那麼它不會返回任何東西。它也不接受任何輸入並在完整的表格上運行。 – user1298426

+0

我不明白那個評論,但正如你已經接受了其他答案,我想你的問題已經解決了。 –