如何从通过对postgres中的多个列查询单个搜索项而返回的集合中按排序顺序首先返回最佳匹配的行?

ipakzgxi  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(288)

背景
我有一张postgres 11的table,像这样:

CREATE TABLE
        some_schema.foo_table (
            id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
            bar_text TEXT,
            foo_text TEXT,
            foobar_text TEXT
        );

它有如下数据:

INSERT INTO some_schema.foo_table (bar_text, foo_text, foobar_text)
        VALUES ('eddie', '123456', 'something0987');
        INSERT INTO some_schema.foo_table (bar_text, foo_text, foobar_text)
        VALUES ('Snake', '12345-54321', 'that_@#$%_snake');
         INSERT INTO some_schema.foo_table (bar_text, foo_text, foobar_text)
        VALUES ('Sally', '12345', '24-7avocado');

 id | bar_text |  foo_text   |   foobar_text   
----+----------+-------------+-----------------
  1 | eddie    | 123456       | something0987
  2 | Snake    | 12345-54321 | that_@#$%_snake
  3 | Sally    | 12345        | 24-7avocado

问题
我需要查询这些列中的每一列,并将值与给定的项(作为app logic的参数传入)进行比较,并确保按排序顺序首先返回最匹配的行(考虑与所有列的比较,而不仅仅是一列)。对于给定的术语,无法提前知道哪列可能更匹配。
如果我使用similarity()函数将给定的项与每个值进行比较,我可以一目了然地看到哪一行在这三列中最匹配,并且可以看到这一行是我希望在排序顺序中排名第一的行。

SELECT 
    f.id,
    f.foo_text, 
    f.bar_text,
    f.foobar_text,
    similarity('12345', foo_text) AS foo_similarity,
    similarity('12345', bar_text) AS bar_similarity,
    similarity('12345', foobar_text) AS foobar_similarity
    FROM some_schema.foo_table f
    WHERE 
    (
        f.foo_text ILIKE '%12345%' 
        OR
        f.bar_text ILIKE '%12345%'
        OR 
        f.foobar_text ILIKE '%12345%'
        )
        ;
 id |  foo_text   | bar_text |   foobar_text   | foo_similarity | bar_similarity | foobar_similarity 
----+-------------+----------+-----------------+----------------+----------------+-------------------
  2 | 12345-54321 | Snake    | that_@#$%_snake |            0.5 |              0 |                 0
  3 | 12345       | Sally    | 24-7avocado     |              1 |              0 |                 0
  1 | 123456      | eddie    | something0987   |          0.625 |              0 |                 0
(3 rows)

很明显,在这种情况下,3号身份证(萨利)是最好的匹配(确切地说,因为它发生了);这是我想先回去的那一排。
但是,由于我事先不知道fooèu text将是最匹配的列,所以我不知道如何定义order by子句。
我认为这是一个很常见的问题,但我还没有发现任何线索,在公平位的so和ddg。
我如何总是在返回的集合中将最匹配的行排在第一位,而不知道哪一列将提供与搜索项的最佳匹配?

bwleehnv

bwleehnv1#

使用 greatest() :

greatest(similarity('12345', foo_text), similarity('12345', bar_text), similarity('12345', foobar_text)) desc

相关问题