Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 如何从每个用户那里获得20个用户和5篇文章?_Database_Ruby On Rails 3_Postgresql_Rdbms - Fatal编程技术网

Database 如何从每个用户那里获得20个用户和5篇文章?

Database 如何从每个用户那里获得20个用户和5篇文章?,database,ruby-on-rails-3,postgresql,rdbms,Database,Ruby On Rails 3,Postgresql,Rdbms,用户可以有许多文章 我想得到20个最近的用户,每个用户有5篇文章 我一直在读,但对于我的场景来说,这似乎太复杂了。然而,文章中提到的查询速度惊人!有人告诉我。也许有一种方法可以合并查询中使用的一些方法 我使用Postgres 9.2,假设“最近”用户的意思是“最近创建的”: 虚拟数据设置 首先,生成一些虚拟数据。我没有费心把它格式化: create table users ( id serial primary key, username text not null,created_at tim

用户
可以有许多
文章

我想得到20个最近的用户,每个用户有5篇文章

我一直在读,但对于我的场景来说,这似乎太复杂了。然而,文章中提到的查询速度惊人!有人告诉我。也许有一种方法可以合并查询中使用的一些方法

我使用Postgres 9.2,假设“最近”用户的意思是“最近创建的”:

虚拟数据设置 首先,生成一些虚拟数据。我没有费心把它格式化:

create table users ( id serial primary key, username text not null,created_at timestamptz not null default current_timestamp );
create table articles (id serial primary key, user_id integer not null references users(id), created_at timestamptz not null default current_timestamp);
insert into users (username) values ('todd'),('bob'),('janet'),('joan'),('jim'),('jolly'),('roger'),('yarr'),('fred');
update users set created_at = current_timestamp + id * INTERVAL '1' MINUTE;
insert into articles(user_id, created_at) select u.id, x from users u cross join generate_series(current_timestamp, current_timestamp + INTERVAL '1' HOUR, INTERVAL '1' MINUTE) x;
PostgreSQL 9.3beta1及以上版本:
LATERAL
现在,这是一个遗憾的时刻,你没有在9.3上;在这里,您可以使用一个横向子查询很好地完成这一切:

SELECT u.username, a.id AS article_id 
FROM (
    SELECT u1.id, u1.username 
    FROM users u1 
    ORDER BY u1.created_at DESC LIMIT 5
) u,
LATERAL (
    SELECT a1.id
    FROM articles a1 
    WHERE a1.user_id = u.id
    ORDER BY a1.created_at DESC LIMIT 5
) a;
见:

然而,由于9.3还没有完全发布,所以不使用它也就不足为奇了

PostgreSQL 9.2及更高版本: 在9.2及以上版本中,您必须使用另一层子查询来解决
横向
支持不足的问题,您将面临一些棘手的解决方案,包括
行数
窗口函数和嵌套子查询。看,

比如:

WITH
last_five_users AS (
        SELECT u1.id, u1.username FROM users u1 ORDER BY u1.created_at DESC LIMIT 5
)
SELECT
        lfa.username, lfa.article_id
FROM
(
        SELECT lfive.username, lfive.id, a.id, row_number() OVER (PARTITION BY a.user_id ORDER BY created_at)
        FROM articles a
        INNER JOIN last_five_users lfive ON (a.user_id = lfive.id)
) AS lfa(username, user_id, article_id, rownum)
WHERE lfa.rownum <= 10;
然后在主查询中使用该选项:

SELECT
  o.username,
  (o.last_articles).*
FROM (
        SELECT
                u.username,
                last_n_articles_for_user(u.id, 10) AS last_articles
        FROM (
                SELECT *
                FROM users u1
                ORDER BY u1.created_at DESC
                LIMIT 5
        ) u
) AS o;

如果在中创建了
索引,这可能会表现得更好,尽管不如9.3中启用的
横向
方法。需要额外的子查询层,因为直接使用
*
语法为用户调用
last\u n\u articles\u将导致每个列调用一次子查询(由于PostgreSQL对行返回函数的内部限制)。

您确实应该尝试提供一些示例数据和预期结果,省去了需要装假的麻烦+1无论如何,为了一个半体面的解释和提及你的版本。定义“最近的用户”。最近创建的?最近活跃?最近发表了一篇文章?非常好的解释和示例的使用+1横向功能看起来确实很有趣,感谢您提到集合函数方法
SELECT
  o.username,
  (o.last_articles).*
FROM (
        SELECT
                u.username,
                last_n_articles_for_user(u.id, 10) AS last_articles
        FROM (
                SELECT *
                FROM users u1
                ORDER BY u1.created_at DESC
                LIMIT 5
        ) u
) AS o;