我们说我有以下架构:
CREATE TABLE author(
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE article(
id SERIAL PRIMARY KEY,
rating NUMERIC NOT NULL,
author_id INTEGER NOT NULL REFERENCES author
);
CREATE INDEX ON article(author_id);
我想获取所有作者及其前五篇文章,如果至少有一篇作者评论> 4。
很有可能写这个:
SELECT au.id AS author,
json_agg(ar.*) AS articles
FROM
author au
JOIN LATERAL
(SELECT *
FROM article
WHERE author_id = au.id
ORDER BY rating DESC LIMIT 5) ar ON (TRUE)
GROUP BY au.id
HAVING any(ar.rating) > 4;
虽然any(ar.rating) > 4
看起来像是每个组的过滤器表达式,但any(ar.rating)
不是聚合值。因此,Postgres拒绝此查询似乎是合理的。是否可以使用HAVING
编写查询?
作为替代方案,我编写此查询以获取结果:
SELECT au.id AS author,
json_agg(ar.*) AS articles
FROM
(SELECT au.*
FROM author au
WHERE EXISTS
(SELECT 1
FROM article
WHERE rating > 4 AND author_id = au.id)) au
JOIN LATERAL
(SELECT *
FROM article
WHERE author_id = au.id
ORDER BY rating DESC LIMIT 5) ar ON (TRUE)
GROUP BY au.id;
然而,这并没有结合分组和检查是否存在具有评级>的文章。 4步一步完成。有没有更好的方法来编写此查询?
答案 0 :(得分:2)
如果您坚持使用ANY
,则必须使用array_agg
将该列聚合为数组。
HAVING
4< ANY(Array_Agg(ar.rating))
但如果任何高于4,则也意味着最大值高于4,因此更具可读性
HAVING
4 < Max(ar.rating)