15

我正在尝试学习 Rails [通过遵循 coursera 中的 SAAS 课程] 并使用 ActiveRecord 处理简单的电影表。

我想显示所有按标题排序的电影。我希望它不区分大小写。

我试过这样做:

Movie.all(:conditions => ["lower(title) = ?", title.downcase],:order => "title DESC")
=>undefined local variable or method `title' for #<MoviesController:0xb4da9a8>

我认为它不识别 lower(title) 。

这是实现不区分大小写排序的最佳方法吗?

谢谢!

4

4 回答 4

21

使用where与不使用all

Movie.where("lower(title) = ?", title.downcase).order("title DESC")

虽然不是很了解这种类型。在这里,您将获得所有标题较低的电影等于title.downcase. 一切都是平等的,你怎么能排序呢title desc

要按小写标题按字母顺序对所有电影进行反向排序:

Movie.order("lower(title) DESC").all
于 2012-08-04T04:57:52.633 回答
9

你必须这样做:

Movie.order("lower(title) DESC").all
于 2012-08-04T05:01:19.670 回答
5

更健壮的解决方案是使用 arel 节点。我建议在Movie模型上定义几个范围:

scope :order_by_title, -> {
  order(arel_table['title'].lower.desc)
}

scope :for_title, (title)-> {
  where(arel_table['title'].lower.eq title.downcase)
}

然后打电话Movie.for_title(title).order_by_title

与列出的其他答案相比,优势在于,如果您为列加上别名或使用列连接到另一个表,并且它们是 sql 转义的.for_title.order_by_title则不会中断。titletitle

就像 rickypai提到的那样,如果您在列上没有索引,数据库会很慢。但是,复制数据并将转换应用到另一列是不好的(正常)形式,因为这样一列可能会与另一列不同步。不幸的是,早期版本的 mysql除了触发器之外不允许有许多替代方案。在 5.7.5 之后,您可以使用虚拟生成的列来执行此操作。然后在不区分大小写的情况下,您只需使用生成的列(这实际上使 ruby​​ 更直接)。

Postgres 在这方面有更多的灵活性,并且可以让您在函数上创建索引而不必引用特殊列,或者您可以使列成为不区分大小写的列。

于 2017-10-20T00:58:31.200 回答
3

让 MySQL 每次都执行大写或小写操作非常昂贵。

我推荐的是有一个title专栏和一个title_lower专栏。这样,您可以轻松地在列上不区分大小写地显示和排序,title_lower而无需在每次排序时让 MySQL 执行上限或下限。

记住要同时索引或至少索引title_lower.

于 2012-08-04T04:58:00.370 回答