【问题标题】:SQL ORDER BY LIKESQL ORDER BY LIKE
【发布时间】:2013-06-09 01:39:51
【问题描述】:

这与我之前位于here 的问题类似。在 SQL(使用 ActiveRecord)中有什么方法可以使用 LIKE 运算符对关系进行排序吗?例如,我正在查询一个关系,其中一列是一个长字符串,通常包含许多逗号分隔值。我想通过将上述列的值与使用 LIKE 的较小字符串匹配的记录排序到前面来排序结果关系(例如,如果我的变量是“西班牙”,那么我想要一个值类似于“爱尔兰,西班牙、法国”将被置于关系的前列)。

我用MyModel.order("country_preferences LIKE ?", country) 之类的东西在活动记录中尝试了这个,但是得到了一个 SQL 错误。执行这种排序的正确方法是什么?

更新(摘自 cmets):

使用 PostgreSQL 9.1。当前的 SQL 错误:http://pastie.org/8037147

country_preference = "Ireland, Spain, France" 的 5 条记录,country_preference = "Ireland, Germany, France" 的 5 条记录。给定一个特定的国家,想要返回一个关系,其中 country_preferences 字符串包含该国家的记录被排在前面。

【问题讨论】:

  • 示例。示例输入、当前输出、所需输出。另外,给出你得到的 SQL 错误。
  • 5 条记录 country_preference = "爱尔兰、西班牙、法国",5 条记录 country_preference = "爱尔兰、德国、法国"。给定一个特定的国家,想要返回一个关系,其中 country_preferences 字符串包含该国家的记录被排在前面。
  • 当前 SQL 错误可以在这里找到:pastie.org/8037147
  • 如果我理解正确,这就是你想要的 MyModel.where("country_preferences LIKE ?", "%#{country}%").order("country_preferences")
  • 这不排除所有“country_preferences LIKE”、“%{country}”返回false的记录吗?我想返回所有记录,只是将匹配的记录排在前面。

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


【解决方案1】:

您的问题是 ActiveRecord 的 order 不支持占位符,因此您必须手动处理 ?,叹息。像这样令人讨厌的事情应该让它过去:

c = ActiveRecord::Base.connection.quote(country)
MyModel.order("country_preferences LIKE '%' || #{c} || '%'")

如果您不想依赖布尔排序,可以将其与 Goat_CO's CASE 结合使用。

【讨论】:

  • 在这里聚会很晚,但我会警告不要在数据库接口中进行字符串插值。他们有成为 SQL 注入向量的坏习惯。
  • @RaySir 这就是为什么你必须小心并使用数据库接口的引用/转义机制的原因。有时您不得不以丑陋的方式来做这件事,因为您拥有的唯一数据库接口太有限且头脑简单,无法做您需要做的事情。
【解决方案2】:

不完全确定 SQL 答案是否有帮助,但您可以按顺序使用 CASE 语句,您的问题不清楚必要的标准,但也许这会有所帮助:

SELECT *
FROM table
ORDER BY CASE WHEN country_preference LIKE '%Ireland%' THEN 1
              WHEN country_preference LIKE '%Spain%' THEN 2
              WHEN country_preference LIKE '%France%' THEN 3
              ELSE 4
          END

【讨论】:

    【解决方案3】:

    如果我的变量是“西班牙”,那么我希望将具有“爱尔兰、西班牙、法国”之类的值的记录排在关系的前面。

    在这种情况下,根据您的变量为值分配权重并按其排序。

     DECLARE @test NVARCHAR(20) = '%Spain%'
    
    SELECT Column1 ,
           CASE WHEN Column1 LIKE @test
                THEN 1
                ELSE 0 
           END [Weight]
    FROM Table
    ORDER BY [Weight] DESC
    

    如果您不想显示“权重”列,请在此查询之上创建一个子查询并省略“权重”列。

    【讨论】:

      【解决方案4】:

      例如如果我的变量是“西班牙”,那么我希望将具有“爱尔兰、西班牙、法国”等值的记录排在关系的前面

      为此,您需要一个案例陈述。它在 Rails 中可能看起来像这样:

      MyModel.order("CASE WHEN country LIKE '%' || ? || '%' THEN 0 ELSE 1 END", country)
      

      虽然老实说我不是 100% 支持后者。不过,SQL 应该如下所示:

      select ...
      from ...
      where ...
      order by case
               when country like '%Spain%' then 0
               else 1
               end
      

      但请注意,这不是有效的查询。 order by 子句基本保证不会使用有效的索引来获取前 10 行。

      【讨论】:

      • AR 不理解 .order 中的占位符,叹息。请记住,AR 使用字符串修饰处理占位符本身,它实际上并没有将它们发送到数据库。
      • 是的。应该根据您自己的答案进行修复。 :-P
      • 数据库人员对 AR 的所有轻蔑和嘲笑都是 (IMO) 应得的。我使用它,但我发誓并直接使用 SQL。
      • @muistooshort:fwiw,它并不比其他 ORM 差多少(续集是我知道的唯一值得注意的例外)...:D
      • 我写了一些 ORM,它们也都是垃圾:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多