排名SQL查询结果 - Ruby on Rails

时间:2018-04-25 20:36:54

标签: sql ruby-on-rails postgresql ruby-on-rails-5

我正在使用PostgreSQL数据库,我有以下查询搜索我的客户数据库并成功完成:

SELECT  "customers".* FROM "customers" WHERE ((("customers"."first_name" IN ('John', 'Doe') OR "customers"."last_name" IN ('John', 'Doe')) OR "customers"."email" IN ('John', 'Doe')) OR "customers"."main_phone" IN ('John', 'Doe'))

等效的Rails查询是:

array = ["John","Doe","111-111-1111"]

Customer.where(first_name: array).or(customers.where(last_name: array)).or(customers.where(email: array)).or(customers.where(main_phone: array))

这很好,但是我想对结果进行排名。例如,如果记录#1匹配名字和姓氏,我希望该记录显示在我的结果的顶部。我怎么能这样做?

1 个答案:

答案 0 :(得分:0)

真正的答案是你应该使用sphinx,弹性搜索或任何其他允许你进行全文搜索和排名结果的工具(甚至是postgresql)。

但是,可以通过为每条记录添加一个简单的match_rank和匹配的字段之和,然后按该字段排序,从数据库构建一个可能的天真排名变通方法。如下所示:

array = ["John","Doe","111-111-1111"]
wrappped_array = "(" + array.map { |v| "'#{v}'" }.join(',') + ")"

Customer.select("customers.*, 
  ((CASE WHEN first_name in #{wrappend_array} THEN 1 ELSE 0 END) +
  (CASE WHEN last_name in #{wrappend_array} THEN 1 ELSE 0 END) +
  (CASE WHEN email in #{wrappend_array} THEN 1 ELSE 0 END) +
  (CASE WHEN main_phone in #{wrappend_array} THEN 1 ELSE 0 END)) as match_rank").
where(first_name: array).
  or(customers.where(last_name: array)).
  or(customers.where(email: array)).
  or(customers.where(main_phone: array)).
  order(match_rank: :desc)