这可能是非常基本的,但我想不出如何编写一个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查询?
答案 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