【问题标题】:"Where" clause with concatenated fields in Rails 3在 Rails 3 中具有串联字段的“Where”子句
【发布时间】:2011-05-22 00:34:00
【问题描述】:

我正在编写一个 Rails 3 应用程序,并且我有一个用户数据库表。用户有 first_name 和 last_name 列。在列出用户的页面上,我想要一个允许用户过滤列表的文本搜索框。他们需要能够在搜索框中键入以下内容之一: - 用户的名字 - 用户的姓氏 - 用户的全名(例如“Smith, John”)

我不知道如何编写将返回这些结果的 where 子句。我得到的最接近的是下面,但是连接字段部分不起作用。

where('(first_name LIKE :search) or (last_name LIKE :search) or ("#{last_name}, #{first_name}" LIKE :search)', :search => "%#{search}%")

我也很想知道是否有更好的方法来处理我的 OR 语句,因为这个子句变得相当笨重。

感谢您的帮助!

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 where-clause


    【解决方案1】:

    您必须记住,where 将转换为 SQL,如果您想将连接的列与搜索字符串进行比较,您必须在数据库/sql 级别执行此操作。

    现在这就是棘手的地方,因为 sql 中的连接因数据库而异。

    在 Postgresql 和 Oracle 中,您可以编写如下内容:

    where("(first_name LIKE :search) or (last_name LIKE :search) or (last_name || ',' || first_name LIKE :search)", :search => "%#{search}%"
    

    不幸的是,Mysql 不支持标准的连接运算符||,使用 mysql 你将不得不使用concat 代替:

    where("(first_name LIKE :search) or (last_name LIKE :search) or (concat(last_name, ',', first_name) LIKE :search)", :search => "%#{search}%"
    

    【讨论】:

    • 那么有没有比 where 子句更好的方法呢?如果可能,我宁愿不添加任何特定于数据库的内容。
    • 另一种选择是事后在内存中执行此操作,但我强烈建议不要这样做。我认为在这里使用where 是最好的选择:您的数据库最适合执行此任务。在这些情况下,恐怕您无法避免添加一些特定于数据库的代码。
    【解决方案2】:

    如果它对其他人有帮助,这是我采用的解决方案:

      def self.search(query)
        if query.blank?
          scoped
        else
          sql = query.split.map do |word|
           %w[first_name last_name].map do |column|
            sanitize_sql ["#{column} LIKE ?", "%#{word}%"]
           end.join(" or ")
          end.join(") and (")
          where("(#{sql})")
        end
      end
    

    感谢 Railscasts 的 Ryan Bates 提供此解决方案。

    【讨论】:

    • 能否请您告诉我您在什么 Railscasts 中找到了这个解决方案。提前致谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    • 1970-01-01
    • 2013-08-24
    相关资源
    最近更新 更多