Rails / SQL:查找具有相同值但大小写不同的属性

时间:2012-11-03 00:52:00

标签: sql ruby-on-rails case-insensitive

这可能是非常基本的,但我想不出如何编写一个SQL查询来查找具有相同字符但大小写不同的字符串。

我正在研究的上下文是一个Rails 3.2应用程序。我有一个带有Name属性的简单Tag模型。我继承了这个模型的数据,它没有存储不区分大小写的值,因此一些用户输入“Tree”之类的东西,而其他用户输入“tree”,现在我们有两个标签真的应该是一个。

所以,我想查询所有这些对,以便我可以合并它们。

到目前为止,我唯一能想到的就是编写一个rake任务,遍历所有这些并检查匹配的值......类似于:

pairs = []
Tag.all.each do |t|
  other = Tag.where( 'name LIKE ?', t.name )
  pairs << [t, other] if other
end

但是,我不确定上述内容是否有效,或者说它在性能方面是否合理。有没有更好的方法来编写可以找到这些匹配对的SQL查询?

3 个答案:

答案 0 :(得分:2)

有一个类似于here

的问题

您可以做的是在模型中创建一个方法来进行不区分大小写的搜索。然而,根据我的经验,ActiveRecord已经进行了不区分大小写的搜索,但以防万一:

def self.insensitive_find_by_tag_name(name)
    Tag.where("lower(name) = ? ", name.downcase)
end

然后删除重复的条目,你可以做这样的事情

Tag.transaction! do
    tags = Tag.insensitive_find_by_tag_name(name)

    tags.last(tags.length() - 1).each do |tag|
        tag.destroy        
    end
end

调用事务以防万一发生任何故障,因此数据库将回滚。抓取所有相同名称的标签,然后删除任何额外的条目。如果您希望剩余的标签条目为小写,则可以执行

tag = tags.first
tag.name = tag.name.downcase
tag.save!

答案 1 :(得分:0)

我并不擅长SQL,但我对此进行了一些研究,发现使用COLLATE子句可以在SQL中使字符串操作区分大小写。 (通常选择不同的操作不区分大小写。)

所以也许你可以试试:

select distinct (name) COLLATE sql_latin1_general_cp1_cs_as
    FROM (
    ... blah blah blah

以下是有关整理的一些文档: http://dev.mysql.com/doc/refman/5.0/en/charset-collate.html

(假设您正在使用mysql我猜)

或者,您也可以通过整理将数据库重新配置为区分大小写。那么您当前的查询可能会不会改变

(假设您具有管理权限和重新配置的能力)

答案 2 :(得分:0)

您应该使用upper()或lower()函数将名称全部转换为大写或小写。

SELECT DISTINCT upper(name)

或者:

SELECT DISTINCT lower(name)

来源:http://www.postgresql.org/docs/9.1/static/functions-string.html

另一个选项(更好的代码可维护性)是使用CITEXT类型,但要执行此操作,您必须修改表结构:http://www.postgresql.org/docs/9.1/static/citext.html