以下是我的查询:
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
它搜索我 friend 的帖子,按他们的评分和日期排序。这个查询中实现的窗口函数让我可以根据
MAX
表上的 Friends
字段限制为每个 friend 返回的行数。但是,我还有一个字段
MIN
,它用于指定我希望从给定 friend 的查询中获得的最小帖子数。这怎么可能?我还想知道 SQL 是否是这些类型查询的最佳选择?我已经尝试过 Neo4j Graph 数据库,虽然它看起来是一个不错的解决方案,但我宁愿避免使用 2 个单独的数据库。
SQLFiddle
架构:
CREATE TABLE friends(
user_id int,
friend_id int,
min int,
max int
);
CREATE TABLE posts(
id int,
title varchar(255),
rating int,
date date,
user_id int
);
假设我们有以下数据:
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, title, rating, date, friend_id)
组合:id
=2 id
=3 id
=4 所以基本上,如果我的
friend_id=2
friend 发布了 1 篇或更多文章,我想要至少 2 篇。如果他发了 3 篇以上的文章,我要不超过 3 篇。 最佳答案
你的解释 in the comment 仍然不成立。根据此解释,您的 min
编号将是没有影响的噪音。
这不是你写的,但这是有道理的:
给定最大的帖子显示位置(外部 LIMIT
),我想首先从每个 friend 那里获取 min
帖子(如果有)。如果之后有空闲插槽,请填写每个 friend 最多 max
帖子。
在这个例子中,如果还有更多的空位可用,那么 friend 2 的 1 ( min
) 帖子具有最高优先级,另外 2 ( max - 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
SQL Fiddle.
笔记
friends.user_id
和 posts.id
为主键。那里缺少您的表定义。 NOT NULL
才有意义。 LATERAL
联接在子查询中仅选择每个 friend 的 max
帖子:row_number()
, not rank()
。混淆两者是一个常见的错误。 date
但它没有显示在您的查询中。也许你真的想要:, row_number() OVER (ORDER BY rating DESC NULLS LAST
, date DESC NULLS LAST) AS rn
DESC NULLS LAST
仅因为 rating
和 date
可能为 NULL:ORDER BY
中使用一个简单的 bool 表达式:ORDER BY (p.rn > f.min), p.rn
这将每个 friend 的
min
帖子放在首位。第二项( p.rn
)给每个 friend 一个平等的机会(先发帖等)。 date
作为标识符。它是标准 SQL 中的保留字,也是 Postgres 中的基本类型名称。 关于sql - 每组最小行数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30001333/