如何为下表编写postgres查询?

时间:2017-04-26 05:17:47

标签: postgresql

这是一个非常奇怪的查询,我不知道如何继续它。 下面是表格。

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循环遍历descendantId,直到达到attr_type x。如果达到attr_type x,即7,9和11,则检查哪一个是true。对于例如那么7是真的 得到type_y类型的兄弟(检查第4行)8并返回它的值。

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

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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