有没有更好的方法来区分没有孩子或无效的父母身份?

时间:2017-12-31 09:58:14

标签: sql postgresql

我想检索给定父母的所有孩子。有三种情况需要区分:

  • 有子节点,以JSON数组返回它们。
  • 没有子节点,但父节点存在,返回一个空的JSON数组。
  • 父母不存在,不返回任何内容。

让孩子们很容易:

select json_agg(child)
from   child
where  child.parent_id = :parent_id

json_agg的一个问题是,当没有行时,它总是返回null。因此,以下内容将返回值为null而不是0行的一行:

select json_agg(child)
from   child
where  false

这增加了区分这三种情况的复杂性。为了解决这个问题,我提出了以下建议:

with
parent as
(
    select id
    from   parent
    where  id = :parent_id
),
result as
(
    select     coalesce(json_agg(child), '[]')
    from       child
    inner join parent
    on         child.parent_id = parent.id
)
select result.*
from   result
where  exists(select * from parent)

这似乎有效,但它相当笨拙。我想知道是否有更好的解决方案。有什么想法吗?

更新

作为请求,这是我想要的:

  • [{...}, {...}, ...]当有孩子的时候。
  • []当没有孩子但父母存在时。
  • 当父母不存在时,
  • no rows

2 个答案:

答案 0 :(得分:4)

在派生表中使用case和聚合,例如:

select children
from (
    select p.id, case when min(c.id) is null then '[]'::json else json_agg(c) end as children
    from parent p
    left join child c on c.parent_id = p.id
    group by p.id
    ) s
where id = :parent_id

答案 1 :(得分:2)

这是聚合函数的正常行为,您只需要隐式GROUP BY <everything down to one row>。那么,使用WHERE子句的聚合版本(&#39; HAVING&#39;)

在那里,您可以检查NULL和/或是否存在父母。

select COALESCE(json_agg(child), '[]')   AS json_object
from   child
where  child.parent_id = :parent_id
HAVING json_agg(child) IS NOT NULL
    OR EXISTS (SELECT * FROM parent WHERE id = :parent_id)

或者,有点干,但更详细...

SELECT
  COALESCE(json_object, '[]'::json)  AS json_object
FROM
(
  select json_agg(child)  AS json_object
  from   child
  where  child.parent_id = :parent_id
)
  your_query
WHERE
  json_object IS NOT NULL
  OR EXISTS (SELECT * FROM parent WHERE id = :parent_id)