2

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

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

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

4

2 回答 2

3

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

值的排序顺序为boolean

FALSE -> TRUE -> NULL

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

NULL -> TRUE -> FALSE

如果您想要TRUE第一个和NULL最后一个,请使用以下NULLS LAST子句ORDER BY

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

当然,NULLS LAST只有当featuredcreated_at 可以是相关的NULL。如果列已定义NOT NULL,则不要打扰。

此外,FALSE将在NULL. 如果你不想区分这两者,你要么回到一个CASE语句,要么你可以抛出NULLIF()or 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'

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

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

于 2012-10-01T21:23:32.620 回答
0

不知道你想在这里实现什么。

我猜你会对结果进行分页。如果是这样,并且您希望始终在顶部显示特色作业,而不管页面如何,那么您应该分别从数据库中提取它们。如果您只想在第一页上显示它们,请按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
于 2012-10-01T19:36:36.647 回答