Activerecord按列排序然后created_at?

时间:2016-02-01 20:27:49

标签: sql ruby-on-rails activerecord

所以我有一个项目表。每个项目的状态可以是“每日”,“每月”,“每年”或“未完成”。

我要做的是创建一个Activerecord(或SQL)查询,它首先按照created_at日期排列未完成项目(通过created_at),然后排列其余项目(无论其状态如何),同时限制返回15的项目总数。

例如,如果我有30个未完成的项目和30个年度项目,则查询返回15个未完成的项目(通过其created_at)。

如果我有10个未完成的项目和30个年度项目,它将返回10个未完成的项目(通过created_at),然后返回5个年度项目(通过created_at) - 返回的未完成项目应该在返回的数组的开头。

如果我没有任何未完成的项目和30个年度项目,它将按其created_at日期返回15个年度项目。

感谢您的帮助!

3 个答案:

答案 0 :(得分:2)

首先,只需定义这样的范围:

class Item < ActiveRecord::Base
  scope :ordered, -> {
    joins("LEFT OUTER JOIN ( SELECT id, created_at, status
                             FROM items
                             WHERE items.status = 'outstanding'
                           ) AS temp ON temp.id = items.id AND temp.status = items.status"
         ).order('temp.created_at NULLS LAST, items.status, items.created_at')
    }
end

神奇之处在于:(希望您的表名为items

  • 使用items左加入outstanding items。因此,对于不具有状态temp.id
  • 的项目,temp.created_atNULL将为outstanding
  • 首先按temp.created_at NULLS LAST排序,以便最后订购不具有状态items的{​​{1}}。然后只需按正常顺序执行:outstanding(这会使相同的状态相互关闭)和items.status

您只能为15个项目运行范围items.created_at的查询:

ordered

答案 1 :(得分:0)

虽然在最坏的情况下(2个查询)不是单个查询,但它解决了您的问题:

Text = (safe_cast<ComboBoxItem^>(AttackDice->SelectedItem))->Content->ToString();

答案 2 :(得分:0)

不确定单个查询,但这是一个适当的解决方案:

scope :ordered,     -> { order(:created_at) }
scope :outstanding, -> { where(status: :outstanding).ordered }

def self.collection
  return ordered.limit(15) if outstanding.count.zero?
  return outstanding.limit(15) if outstanding.count >= 15
  outstanding + ordered.limit(15 - outstanding.count)
end

Item.collection # will return the array of your records