【问题标题】:Find records where field value is all LOWERCASE查找字段值全部为 LOWERCASE 的记录
【发布时间】:2015-11-17 12:05:21
【问题描述】:

在 Rails 3.2 应用程序中,我有一个 Tag 模型,并希望查找 name:string 字段中的值为全部小写的所有记录。

因此,activerecord 查询(在 Postgres 上)将返回 Tag(id: 1, name: 'test') 而不是 Tag(id:2, name: 'Test')

我确信有一种简单的方法可以做到这一点,但我无法生成有效的查询!

【问题讨论】:

  • 感谢 ROR 开发人员,但我所追求的是所有 Tagsnames 只有小写字母,即 'test'、'banana'、'ror developer' 而不是 '测试”、“香蕉”或“ROR 开发人员”。
  • 这两个答案有细微的差别,你应该清楚你想要的是所有列的值与其小写表示相同的行,还是列的值没有小写字母以外的字符。
  • 是的,非常正确大卫。两者都可以接受,尽管我最理想的做法是 exclude 名称包含任何大写字符的标签。但最后我根据 Brad 的回答确定了一个正则表达式查询,然后做了相反的事情,regex: '^[a-z0-9]+$' 查找名称仅包含数字和小写字母的标签,因为这返回了更少的不相关查询。奇怪的是,“正则表达式方式”不仅更加灵活,而且在生产中实际上快了一倍!
  • 性能可以通过正则表达式在到达不在所需集合中的字符时返回 false 来解释,这在字符串以大写字符开头时是最佳的。无需转换所有内容,然后与原始文件进行比较。
  • 伟大的大卫。在数据库上运行一些统计数据显示,在 109,756 个当前标签中,99.17% 以大写字母开头。再次有趣的是,查询 Tag.where('name ~ :regex', regex: '^[A-Z]').count 仍然比 '^[a-z0-9]+$' 正则表达式和计数长近 50%(即 100 毫秒对 70 毫秒),即使使用热 postgres 缓存。

标签: sql ruby-on-rails ruby-on-rails-3 postgresql activerecord


【解决方案1】:

这应该可行:

Tag.where('name = lower(name)')

如果name 等于lower(name),则表示name 是小写的。

【讨论】:

  • 感谢 Mischa! 你的查询是最优雅和最精确的查询,尽管当我在我的生产数据库(Heroku / Postgres)上测试性能时,标签数不到 110,000,并且在数据库缓存已预热,您的查询平均 140 毫秒,而布拉德的正则表达式答案 不到 70 毫秒。这真让我吃惊——谁能想到“现在你有两个问题”导致了最快的查询!?
【解决方案2】:

您可以使用正则表达式搜索所有小写字母,例如:

Tag.where('name ~ :regex', regex: '^[a-z]+$')

【讨论】:

  • name 包含重音字符时,这将返回不正确的结果,例如é.
  • 如果您需要对非英文字符的支持,您可以在stackoverflow.com/a/5005122/525478尝试正则表达式
  • 这适用于 postgresql。如果您使用的是 MySQL:Tag.where("name REGEXP ?", '^[a-z]+$')
  • 谢谢布拉德!您的查询是测试中最快的查询,尽管您在活动记录表达式中有拼写错误,但它应该读作 ...('name ~ :regex',...),因为 ~* 表示 Postgres 的大小写-不敏感正则表达式匹配。如果您更正您的答案,我会将其标记为已接受。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多