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