背景
我有一张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。
我如何总是在返回的集合中将最匹配的行排在第一位,而不知道哪一列将提供与搜索项的最佳匹配?
1条答案
按热度按时间bwleehnv1#
使用
greatest()
: