繁体   English   中英

Active Record Query中基于时间的优先级

[英]Time based priority in Active Record Query

我有一个包含工作列表的表,显示时通常按 created_at 字段降序排序。 我正在添加一个“特色”布尔标志,这将使客户能够更多地了解他们的工作列表。 如果工作不到 X 天,我希望将特色列表固定在搜索结果的顶部。 我将如何通过现有查询进行修改以支持这一点?

Jobs.where("expiration_date >= ? and published = ?", Date.today, true).order("created_at DESC") 

当前查询拉回所有当前已发布的作业,按 created_at 排序。

与其他一些数据库(如 Oracle)不同,PostgreSQL 具有功能齐全的boolean类型。 您可以直接ORDER BY子句中使用它,而无需应用CASE语句 - 这对于更复杂的情况非常有用。

boolean值的排序顺序是:

FALSE -> TRUE -> NULL

如果您ORDER BY bool_expression DESC ,则将顺序反转为:

NULL -> TRUE -> FALSE

如果您首先想要TRUE ,最后想要NULL ,请使用ORDER BYNULLS LAST子句

ORDER BY (featured AND created_at > now() - interval '11 days') DESC NULLS LAST  
       , created_at DESC

当然, NULLS LAST只有当相关featuredcreated_atNULL 如果列被定义为NOT NULL ,那么不要打扰。

此外, FALSE将排在NULL之前。 如果你不想区分这两者,你要么回到CASE语句,要么你可以抛出NULLIF()COALESCE()

ORDER BY NULLIF(featured AND created_at > now() - interval '11 days'), FALSE)
                                                                DESC NULLS LAST
       , created_at DESC

表现

注意,我是如何使用的:

created_at > now() - interval '11 days'

不是

now() - created_at < interval '11 days'

在第一个例子中,右边的表达式是一个计算一次的常数。 然后可以使用索引来查找匹配的行。 非常有效率。

后者通常不能与索引一起使用。 必须为每一行计算一个值,然后才能根据右侧的常量表达式进行检查。 如果可以避免,请不要这样做。 曾经!

不确定你想在这里实现什么。

我想你会对结果进行分页。 如果是这样,并且您希望始终在顶部显示特色作业,而不管页面如何,那么您应该单独从数据库中提取它们。 如果您只想在第一页上显示它们,请按以下方式published

Jobs.where("expiration_date >= ?", Date.today).order("published DESC, created_at DESC") 

如果你想分别拉动它们:

@featured_jobs = Jobs.where("expiration_date >= ? and published = ?", Date.today, true).order("created_at DESC")
@regular_jobs = Jobs.where("expiration_date >= ? AND published = ?", Date.today, false).order("created_at DESC") #Paginate them too ... depends on the gem you're using

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM