【问题标题】:Object.limit(x).sum(:value) ignores the limit(x) -- why?Object.limit(x).sum(:value) 忽略了 limit(x) - 为什么?
【发布时间】:2014-01-29 17:43:36
【问题描述】:

我正在使用 HourlyMetrics 编译一些网站统计数据,发现了一些奇怪的东西。

这是我本地开发环境最近 24 小时的统计数据。

irb(main):017:0> HourlyMetric.order('`to` DESC').limit(24).map(&:value)
  HourlyMetric Load (2.0ms)  SELECT `hourly_metrics`.* FROM `hourly_metrics` ORDER BY `to` DESC LIMIT 24
=> [0, 0, 0, 0, 10, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

我只是想要总数,但我暂时忘记了语法并尝试了两种不同的方法:

irb(main):016:0> HourlyMetric.order('`to` DESC').limit(24).sum(&:value)
  HourlyMetric Load (2.3ms)  SELECT `hourly_metrics`.* FROM `hourly_metrics` ORDER BY `to` DESC LIMIT 24
=> 13

irb(main):018:0> HourlyMetric.order('`to` DESC').limit(24).sum(:value)
   (1.3ms)  SELECT SUM(`hourly_metrics`.`value`) AS sum_id FROM `hourly_metrics` LIMIT 24
=> 21

似乎sum(:value) 正在生成21,因为这是HourlyMetrics所有 记录的总和。所以我知道它来自哪里,但是有人可以帮我理解为什么在我使用limit 范围时sum(:value) 没有范围吗?

【问题讨论】:

  • 这很奇怪。我在 ruby​​ 1.9.3 / Rails 3.2.13 上遇到了同样的故障。 User.limit(1).sum(:id) 总是返回相同的(错误的)数字
  • @MrYoshiji 这是因为 SQL 的工作方式。 User.limit(1).sum(:id) 将生成 SQL select sum('id') from users limit 1 并且作用域 limit 1 在此处正确应用于聚合函数 sum 的结果。仅仅因为它在 ruby​​ 代码中以一种顺序出现并不意味着操作在 SQL 中以相同的顺序执行。
  • 哦,我现在看到了...谢谢@mcfinnigan!

标签: mysql sql ruby-on-rails ruby


【解决方案1】:

作用域的,只是作用域是在聚合值的结果之后应用的,而且由于聚合是跨越表中的所有行,所以它只返回一行。 p>

您的第二个陈述大致类似于:

SELECT * FROM (SELECT SUM(value) from hourly_metrics) limit 24;

这就是结果让你感到困惑的原因。

重申一下 - 聚合函数 SUM 返回 1 行,其范围为 LIMIT 24

【讨论】:

  • 你的解释很有道理!但是,这是非常出乎意料/奇怪的行为。我得到那个 ActiveRecord 或任何懒惰地评估它们的人,并保留为了 SQL 优化而乱序处理它们的权利。但是,我想我会认为当它会改变结果时不这样做会很聪明。这是否属于 ActiveRecord 中的错误,或者只是程序员需要注意的问题?
  • @isthmuses 它被归类为一个陷阱,公平地说,ActiveRecord 不能真正被指望捕捉到这种东西,因为它的工作是成为数据库和你之间的抽象层 - 它正在运行假设您知道自己在做什么,所以您要求它做的就是您希望它做的:-)
猜你喜欢
  • 1970-01-01
  • 2011-03-06
  • 1970-01-01
  • 2020-10-22
  • 2016-04-19
  • 1970-01-01
  • 2021-04-25
  • 2020-03-08
  • 2022-12-23
相关资源
最近更新 更多