Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 有没有更好的方法来区分无子项或无效的父项标识符?_Sql_Postgresql - Fatal编程技术网

Sql 有没有更好的方法来区分无子项或无效的父项标识符?

Sql 有没有更好的方法来区分无子项或无效的父项标识符?,sql,postgresql,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

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

  • 如果存在子项,则以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)
这似乎有效,但相当笨拙。我想知道是否有更好的解决办法。有什么想法吗

更新

根据要求,这是我想要的:

  • [{…},{…},…]
    当有子对象时
  • []
    当没有子项但父项存在时
  • 父级不存在时,无行

这是聚合函数的正常行为,您只需要有一个隐式的
分组依据
。那么,使用WHERE子句的聚合版本('HAVING')

在那里,您可以检查
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)

大小写
与派生表中的聚合一起使用,例如:

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

有json_agg(child)不是空的
?我需要区分这3种情况。添加
使json_agg(child)不为空
将不允许我区分
父项存在但当前没有子项
情况,如果我是对的话?请回答您的问题,并根据该数据添加一些和预期输出。求你了,@a_horse_和_no_name我添加了预期的输出。这些信息够了吗?你能解释一下你为什么要做
min(c.id)
?它只检查是否有子项(注意,他也是按
parent.id
分组的,不能检查
c.id
而周围没有聚合…(尽管它似乎与
COALESCE(json_agg(c),“[]”:json)具有相同的效果)
)@KevinDeGrote规划师将有效地使用“类似宏的扩展”将条件传播到内部查询。(假设内部查询是一个视图,因为子查询也被称为内联视图,规划器可以很容易地理解为处理视图,所以…)如果没有这样的逻辑,SQL将像驴子球一样。(更严重的是,SQL是一种“声明性”语言,而不是大多数人都熟悉的“命令式”语言。这意味着,乐观主义者/规划者/任何你喜欢的术语都可以选择它认为合适的任何方式来解决你所声明的问题。这给了它很大的“为你聪明”的空间。)@KevinDeGrote-当有疑问时,对两个查询使用
解释分析
,计划将是相同的。如果
min(c)为空
似乎有问题,可以使用
count(c)=0
这可能更直观。@MatBailie-谢谢你的宝贵评论。有趣的方法。我们只需要重复一下
json\u agg(child)
。这基本上是我最初的问题:)。@KevinDeGrote-我个人认为克林的答案比我的好。
左连接的成本与
存在的成本相同,它对
案例更加严格,而不是
COALESCE()
,只有
:parent\u id
参数一次…这很“笨拙”,但在我看来不是一个黑客。
COUNT(c.id)>0会让你感觉更好吗?有道理
count(c.id)=0感觉确实更正确,但我想我在这里太迂腐了。