每组的最小行数

时间:2015-05-02 10:45:26

标签: 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_id = f.friend_id)
    WHERE f.user_id=1
) AS subq
WHERE (subq.rnk <= subq.max)
LIMIT 10

它会搜索我朋友的帖子,按照评分和日期排序。在此查询中实现的窗口函数允许我根据MAX表上的Friends字段限制为每个朋友返回的行数。

但是,我还有一个字段MIN,用于指定查询给定朋友的最小帖子数。怎么可能?

我也想知道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)组合符合以下条件:

  1. 来自朋友的1到3个帖子id = 2
  2. 来自id = 3
  3. 的朋友的0到5个帖子
  4. 来自id = 4
  5. 的朋友的2到10个帖子

    所以基本上,如果我的朋友friend_id=2发布了一篇或多篇文章,我至少想要其中的两篇。如果他发表了超过3篇文章,我希望不超过3篇。

1 个答案:

答案 0 :(得分:0)

我错过了什么吗?你不能只在and subq.rnk >= subq.min条款中添加where吗?

SELECT *
FROM (SELECT f.max, f.min, p.friend_id, p.id, p.title, p.rating
             row_number() over (partition by p.user_id
                                order by p.rating DESC, p.id DESC
                               ) as rnk
      FROM posts p INNER JOIN
           friends f
           ON p.friend_id = f.user_id
      WHERE f.user_id = 1
     )  subq
WHERE subq.rnk <= subq.max and subq.rnk >= subq.min