【问题标题】:How to order grouped columns in an ActiveRecord Postgres query如何在 ActiveRecord Postgres 查询中对分组列进行排序
【发布时间】:2013-09-01 23:55:06
【问题描述】:

我正在尝试为博客构建一个侧边栏,其中包含非常标准的存档信息,例如:

2013 年 8 月:3 个帖子

2013 年 7 月:5 个帖子

2013 年 6 月:4 个帖子

...等

什么 ActiveRecord 查询将提供这些信息(monthyearcount)按时间倒序排序?

Post 模型非常简单——titlebodycreated_atmodified_at 列。我正在尝试编写 ActiveRecord/Postgres 查询,该查询为我提供按月和年分组的帖子数(如上所列)。以下查询成功地做到了这一点:

Post.select('count(*) as count','extract(year from created_at) as year', 'extract(month from created_at) as month').group('year','month')

但我想明确地按时间顺序对列进行倒序排序(所以 2013 年 8 月在列表中高于 2013 年 7 月),这就是一切都变得混乱的地方。我尝试了以下查询失败,只是为了开始:

Post.select('count(*) as count','extract(year from created_at) as year', 'extract(month from created_at) as month').group('year','month').order(:year => :desc)

它产生以下 SQL:

SELECT count(*) as count, extract(year from created_at) as year, extract(month from created_at) as month FROM "posts" GROUP BY year, month ORDER BY "posts"."year" DESC

还有以下错误:

PG::UndefinedColumn: ERROR: column posts.year does not exist

如果我使用.order(:count => :desc) 按计数排序,查询实际上会运行,但它似乎实际上并没有按照我预期的方式排序(切换到:asc 并没有什么不同)。

我搜索了 SO 和 google,但无济于事。我也尝试过按created_at 排序,但它会引发ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "posts.created_at" must appear in the GROUP BY clause or be used in an aggregate function 错误。理想情况下,我会运行一个简单的Post.order(:created_at => :desc),然后对排序良好的结果运行分组查询,但我不知道如何。

非常迷茫...如何检索包含 yearmonthcount 列的帖子,但按时间顺序倒序排列结果组?

非常感谢您的帮助!

【问题讨论】:

  • .order('year desc') 有效吗?这是哪个版本的 Rails?我的 3.2 根本不喜欢你的 selectorder 电话。
  • @mu 太短,使用 Rails 4.0.0,Ruby 2.0.0-p247
  • 这解释了我在测试时遇到的问题,我手头没有设置 Rails4。我猜.order('year desc') 会起作用,因为 AR 应该将字符串传递给不受干扰的 SQL(不像当你使用哈希时 AR 认为它知道它在做什么但实际上并不知道)。

标签: sql ruby-on-rails postgresql activerecord ruby-on-rails-4


【解决方案1】:

并非所有数据库都允许您在 GROUPORDER 子句中引用派生列名。我自己不了解 PostgreSQL,但也许它支持相对列引用。试试这个:

SELECT count(*) as count
     , extract(year from created_at) as year
     , extract(month from created_at) as month 
FROM "posts" 
GROUP BY 2, 3 
ORDER BY 2 DESC, 3 DESC

如果这不起作用,这应该:

SELECT count(*) as count
     , extract(year from created_at) as year
     , extract(month from created_at) as month 
FROM "posts" 
GROUP BY extract(year from created_at), extract(month from created_at)
ORDER BY extract(year from created_at) DESC, extract(month from created_at) DESC

【讨论】:

    猜你喜欢
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    相关资源
    最近更新 更多