2017-04-26 78 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

我不明白那个评论,但正如你已经接受了其他答案,我想你的问题已经解决了。 –