2

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

我正在处理的上下文是 Rails 3.2 应用程序。我有一个带有 Name 属性的简单 Tag 模型。我继承了这个模型的数据,它不区分大小写存储值,所以一些用户输入诸如“树”之类的内容,而其他用户输入“树”,现在我们有两个真正应该是一个的标签。

所以,我想做一个查询来找到所有这些对,以便我可以合并它们。

到目前为止,我唯一能想到的就是编写一个 rake 任务,循环遍历它们并检查匹配的值......比如:

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

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

4

3 回答 3

2

这里有一个类似的问题

您可以做的是在您的模型中创建一个方法来执行不区分大小写的搜索。然而,从我的经验来看,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!
于 2012-11-03T07:01:11.397 回答
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-collat​​e.html

(假设你使用的是 mysql 我猜)

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

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

于 2012-11-03T01:07:22.127 回答
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

于 2012-11-03T05:53:13.467 回答