Sql 每个组的最小行数
以下是我的疑问:Sql 每个组的最小行数,sql,postgresql,neo4j,greatest-n-per-group,sql-limit,Sql,Postgresql,Neo4j,Greatest N Per Group,Sql Limit,以下是我的疑问: SELECT * FROM ( SELECT f.max, f.min, p.user_id, p.id, p.title, p.rating, RANK() OVER ( PARTITION BY p.user_id ORDER BY p.rating DESC, p.id DESC ) AS rnk FROM posts AS p INNER JOIN friends AS f ON (p.user_i
SELECT *
FROM (
SELECT f.max, f.min, p.user_id, p.id, p.title, p.rating,
RANK() OVER (
PARTITION BY p.user_id
ORDER BY p.rating DESC, p.id DESC
) AS rnk
FROM posts AS p
INNER JOIN friends AS f ON (p.user_id = f.friend_id)
WHERE f.user_id=1
) AS subq
WHERE (subq.rnk <= subq.max)
LIMIT 10
假设我们有以下数据:
INSERT INTO friends VALUES
(1,2,1,3)
, (1,3,0,5)
, (1,4,2,10);
INSERT INTO posts VALUES
(1, 'posts1', 2, now(), 2)
, (2, 'posts2', 1, now(), 2)
, (3, 'posts3', 5, now(), 2)
, (4, 'posts4', 2, now(), 2)
, (5, 'posts5', 11, now(), 2)
, (6, 'posts6', 7, now(), 2)
, (7, 'posts7', 3, now(), 2)
, (8, 'posts8', 4, now(), 3)
, (9, 'posts9', 1, now(), 3)
, (10, 'posts10', 0, now(), 3)
, (11, 'posts11', 7, now(), 3)
, (12, 'posts12', 3, now(), 3)
, (13, 'posts13', 2, now(), 3)
, (14, 'posts14', 4, now(), 4)
, (15, 'posts15', 9, now(), 4)
, (16, 'posts16', 0, now(), 4)
, (17, 'posts17', 3, now(), 4)
, (18, 'posts18', 2, now(), 4)
, (19, 'posts19', 1, now(), 4)
, (20, 'posts20', 2, now(), 4);
因此,如果可能的话,我希望看到post_id、标题、评级、日期、friend_id组合符合以下条件:
id为2的朋友的1到3篇帖子
id=3的朋友的0到5篇帖子
id=4的朋友的2到10篇帖子
所以基本上,如果我的friend_id=2的朋友发表了1篇或更多的文章,我至少想要2篇。如果他发表的文章超过3篇,我就不要超过3篇。我遗漏了什么吗?您不能将and subq.rnk>=subq.min添加到where子句中吗
我认为从neo4j/cypher的角度来看,这才是你真正想要做的
match (u:User {id: 1})-[r:FOLLOWS]->(p:Publisher)
with u, p, r
match p-[:PUBLISHED]-(i:Item)
with u, p, r, i
order by i.name
return u.name, p.name, i.name
skip 5
limit 2
您只需要参数化最小值和最大值,并在运行时绑定它们,这将涉及两个查询,而不是一个查询,但我认为这仍然是一个优雅的解决方案。我以前尝试过在skip和limit中包含属性,但cypher显然还不支持。它需要一个参数或无符号整数
match (u:User {id: 1})-[r:FOLLOWS]->(p:Publisher)
with u, p, r
match p-[:PUBLISHED]-(i:Item)
with u, p, r, i
order by i.name
return u.name, p.name, i.name
skip {min}
limit {max}
比如说,如果你每天发2-5篇文章,我希望你每天发2-5篇
很如果你只发布一个,这是好的,我将有唯一的
一个职位
你的解释仍然不合情理。根据此解释,您的最小值将是无影响的噪声
这不是你写的,但这是有意义的:
给出了一个最大的显示槽为职位的外部限制,我想得到最小的职位,从每个朋友首先如果可用。如果在那之后还有空闲时间,请为每个朋友添加最多个帖子
在这个例子中,这将是1分钟后,从朋友2与最高优先级和另外2个最大最小的职位,如果更多的插槽仍然可用
如果没有足够的时间来分配每个优先权,那么哪些帖子会被裁掉是任意的。我继续说,并假设每个人的第一个职位应该首先被选中,等等
其余部分仍然是随意的,但如果您能够制定需求,则可以很容易地解决
SELECT *
FROM friends f
, LATERAL (
SELECT *
, row_number() OVER (ORDER BY rating DESC NULLS LAST, id DESC) AS rn
FROM posts p
WHERE user_id = f.friend_id -- LATERAL reference
ORDER BY rating DESC NULLS LAST, date DESC NULLS LAST
LIMIT f.max -- LATERAL reference
) p
WHERE f.user_id = 1
ORDER BY (p.rn > f.min) -- minimum posts from each first
, p.rn
LIMIT 10; -- arbitrary total maximum
笔记
假设friends.user_id和posts.id是主键。这里缺少您的表格定义
所有其他列都应该定义为NOTNULL,这样才有意义
使用横向联接在子查询中仅选择每个朋友的最大发布次数:
在子查询中使用。混淆两者是一个常见的错误
您提到了日期,但它没有显示在您的查询中。也许你真的想要:
, row_number() OVER (ORDER BY rating DESC NULLS LAST
, date DESC NULLS LAST) AS rn
DESC NULLS仅因评级和日期可以为NULL而持续:
在Postgres中,可以按以下顺序使用简单的布尔表达式:
这将每个朋友的最小帖子放在第一位。第二项p.rn给予每个朋友同等的机会,如先发邮件、先发邮件等
不要使用日期作为标识符。它在标准SQL中是一个保留字,在Postgres中是一个基本类型名
您可以提供示例表模式以及数据和示例输出吗?但是,我还有一个字段MIN,用于指定我希望从给定朋友的查询中获得的最少帖子数。这怎么可能呢?我无法得到你们想要的东西,至少我无法得到你们需要用这个列来查询的东西MIN@vivek谢谢,这个问题现在更新了5到10篇文章?也就是说,如果你的可用帖子少于5篇,你就不想显示任何帖子了?@JakubKania不,这意味着至少有5篇,如果可能的话。不幸的是,这是行不通的。rnk是一个序列号,因此写入subq.rnk>=subq.min将排除最上面的subq.min帖子。谢谢,这非常有用!
SELECT *
FROM friends f
, LATERAL (
SELECT *
, row_number() OVER (ORDER BY rating DESC NULLS LAST, id DESC) AS rn
FROM posts p
WHERE user_id = f.friend_id -- LATERAL reference
ORDER BY rating DESC NULLS LAST, date DESC NULLS LAST
LIMIT f.max -- LATERAL reference
) p
WHERE f.user_id = 1
ORDER BY (p.rn > f.min) -- minimum posts from each first
, p.rn
LIMIT 10; -- arbitrary total maximum
, row_number() OVER (ORDER BY rating DESC NULLS LAST
, date DESC NULLS LAST) AS rn
ORDER BY (p.rn > f.min), p.rn