我Articles
有{_ 1}}。当Metric.name =“得分”时,我希望通过特定的Metric.value订购Metrics
。 (Articles
将各种文章统计信息记录为“名称”和“价值”对。文章可以有多个指标,甚至多个“得分”,尽管我只对最近的订购感兴趣。)
Metric
我正在努力写一个范围来做这个 - 任何想法?像这样的东西?
class Article
has_many :metrics
class Metric
# name :string(255)
# value :decimal(, )
belongs_to :article
更新
一篇文章可能会在scope :highest_score, joins(:metrics).order('metrics.value DESC')
.where('metrics.name = "score"')
表格中存储许多“得分”(因为它们是按周/每月/每年等计算的),但我只对使用第一个找到的(大多数)感兴趣最近)任何一篇文章的“得分”。 metrics
模型有一个default_scope,可确保DESCending排序。
修正了'metrics.value DESC'报价位置的拼写错误。
与我的手机朋友uber rails hacker交谈,看起来我可能需要一个原始的SQL查询。现在我已经超越了我的头脑......(如果有帮助,我正在使用Postgres。)
谢谢!
更新2:
感谢Erwin的SQL查询建议,我有一个原始的SQL查询可以运行:
Metric
它给出了一个表示文章数据的哈希数组(但不是文章对象??)。
后续问题:
任何将这个转换回Rails的activerecord查询的方法? (所以我可以在范围内使用它)
解决方案更新:
如果有人正在寻找最终的ActiveRecord查询 - 非常感谢Mattherick帮助我完成了question。最终的工作查询是:
SELECT a.*
FROM articles a
LEFT JOIN (
SELECT DISTINCT ON (article_id)
article_id, value
FROM metrics m
WHERE name = 'score'
ORDER BY article_id, date_created DESC
) m ON m.article_id = a.id
ORDER BY m.value DESC;
article_list_by_desc_score = ActiveRecord::Base.connection.execute(sql)
谢谢大家!
答案 0 :(得分:3)
查询可以这样工作:
SELECT a.*
FROM article a
LEFT JOIN (
SELECT DISTINCT ON (article_id)
article_id, value
FROM metrics m
WHERE name = 'score'
ORDER BY article_id, date_created DESC
) m ON m.metrics_id = a.metrics_id
ORDER BY m.value DESC;
首先,在子查询value
中为每篇文章检索name = 'score'
的“最新”m
。在相关答案中对使用过的技术有更多解释:
你似乎成了一个非常基本的误解的受害者:
但我只对使用第一个(最近的)“得分”感兴趣 对于任何一篇文章。度量标准模型具有default_scope,可确保DESCending排序。
表格中有 no“自然顺序”。在SELECT
中,您需要ORDER BY
明确定义的标准。出于此查询的目的,我假设列metrics.date_created
。如果您没有任何类型,那么无法定义“最新”并被迫从多个符合条件的行中回退到任意选择:
ORDER BY article_id
这不可靠。 Postgres会挑选一排。可能会随着表的任何更新或查询计划中的任何更改而更改。
下一步,LEFT JOIN
到表article
和ORDER BY value
。 NULL
排序最后,所以没有限定值的文章最后一次。
注意:一些不那么聪明的ORM(我担心Ruby的ActiveRecord就是其中之一)使用非描述性和非独特的 id
作为主要名称键。您必须适应您未提供的实际列名称。
应该体面。就Postgres而言,这是一个“简单”的查询。表metrics
上的部分多列索引会使其更快:
CREATE INDEX metrics_some_name_idx ON metrics(article_id, date_created)
WHERE name = 'score';
此顺序中的列。在PostgreSQL 9.2+中,您可以添加列值以使仅索引扫描成为可能:
CREATE INDEX metrics_some_name_idx ON metrics(article_id, date_created, value)
WHERE name = 'score';