我的问题的小提琴可以在https://dbfiddle.uk/?rdbms=postgres_10&fiddle=3cd9335fa07565960c1837aa65143685上找到。
我有一个简单的表格布局:
class
person: belongs to a class
Run Code Online (Sandbox Code Playgroud)
我想选择所有班级,对于每个班级,我想要按降序排列的所属人员的前两个人员标识符。
我通过以下查询解决了这个问题:
select c.identifier, array_agg(p.identifier order by p.name desc) as persons
from class as c
left join lateral (
select p.identifier, p.name
from person as p
where p.class_identifier = c.identifier
order by p.name desc
limit 2
) as p
on true
group by c.identifier
order by c.identifier
Run Code Online (Sandbox Code Playgroud)
注意:我可以在SELECT
子句中使用相关子查询,但作为学习过程的一部分,我试图避免这种情况。
如您所见,我order by p.name desc
在两个地方申请:
有没有办法避免这种情况?我的坚持:
首先,显然我不能删除order by
子查询中的 ,因为这会给出一个不符合我上述要求的查询。
其次,我认为order by
聚合函数中的 不能被遗漏,因为子查询的行顺序不一定保留在聚合函数中?
我应该重写查询吗?
我想验证一json[]
列the_array
不为空。对于普通数组,我可以检查:
the_array != '{}'
Run Code Online (Sandbox Code Playgroud)
但是,这不适用于 a json[]
,如下所示:
select '{}'::json[] != '{}'
ERROR: could not identify an equality operator for type json
Run Code Online (Sandbox Code Playgroud)
我可以改用以下检查:
array_length(the_array, 1) != null // yes, array_length on an
empty array returns null
Run Code Online (Sandbox Code Playgroud)
我担心这array_length()
会遍历整个数组以计算项目数,然后返回该计数。就我而言,我不需要数组的实际大小,我只需要知道它是否为空。
那么,是否array_length()
遍历整个数组?如果是这样,是否有更好的方法来检查 json 数组是否为空?
我的问题的小提琴可以在https://dbfiddle.uk/?rdbms=postgres_10&fiddle=e387589d446d9c9a952294f8c7a98494上找到。
我有简单的表格布局:
class
person: belongs to a class
room: belongs to a class
Run Code Online (Sandbox Code Playgroud)
以下查询选择嵌入了人员的所有类:
select class.identifier, array(select person.identifier from person where person.class_identifier = class.identifier) as persons
from class
order by class.identifier;
Run Code Online (Sandbox Code Playgroud)
在试验和学习更多有关相关子查询的信息时,我注意到可以通过用 aLEFT JOIN
组合替换相关子查询来重写上面的查询GROUP BY
:
select class.identifier, array_agg(person.identifier) as persons
from class
left join (
select person.identifier, person.class_identifier
from person
) as person
on class.identifier = person.class_identifier
group by class.identifier
order by class.identifier;
Run Code Online (Sandbox Code Playgroud)
请注意,我假设每个班级至少有一个人。如果没有,我可以添加coalesce()
周围json_agg
。
在我的第二种情况下,我将选择所有嵌入人员和房间的类。让我们首先以与上面第一个查询相同的方式编写:
select class.identifier, array(select …
Run Code Online (Sandbox Code Playgroud)