Postgres:如何在用户输入的每个单词上使用 LIKE,并对结果进行 AND-ing

Postgres: how to use LIKE on every word of user input, AND-ing the results

在 postgresql (9.6) 中,给定 'alice chaplin' 或 'alice' 或 'alice chaplin meyer' 以及 'lic chapl' 类型的可变长度用户输入,我想搜索对于在名字或姓氏列中包含 'alice' 的记录(并且在名字或姓氏中包含 'chaplin'(并且在名字或姓氏中包含 'meyer')),等等

我决定使用 ILIKE %searchterm% 进行匹配,因此查询大概是这样的:

... where
     ((lastname ILIKE '%' || SEARCHTERM1 || '%') OR (firstname ILIKE '%' || SEARCHTERM1 || '%')) 
 AND ((lastname ILIKE '%' || SEARCHTERM2 || '%') OR (firstname ILIKE '%' || SEARCHTERM2 || '%')) 
 AND etc.

经过多次尝试和搜索,没有任何结果可以解决这个问题...作为最后的手段,我将编写一个非常程序化的 pgplsql 函数,它循环遍历拆分的搜索字符串,与 ILIKE 结果相交, 但必须有一些更惯用的 SQL 方法来解决这种 运行 的工厂问题。

您可以使用 string_to_array 将输入字符串转换为单词数组。然后可以用unnest把数组转成(虚)table,对单词进行操作前后加'%'。最后,您可以使用 ILIKE ALL (SELECT ...) 进行 ALL 比较。这 ALL 实际上将是 AND-ing 结果,如您所愿。

WITH q AS
(
  SELECT 'Alice Chaplin Meyer'::text AS q
)
, words AS
(
SELECT 
  '%' || word || '%' AS wordish
FROM
  q
  JOIN LATERAL unnest(string_to_array(q, ' ')) AS a(word) ON true
)
SELECT
    *
FROM
    t
WHERE
    concat_ws(' ', first_name, last_name) ILIKE ALL(SELECT wordish FROM words)

您可以在 http://rextester.com/LNB38296

查看所有内容

参考文献:

  1. string_to_array and unnest
  2. Using ALL

注意:这可能可以简化,但我更喜欢 step-by-step 方法。