2016-12-11 2 views
0

У меня есть схемы вроде следующего (только в качестве примера):Найти строки, где минимальное количество столбцов соответствующей шаблон

CREATE TABLE example (
    id int primary key 
, text1 text 
, text2 text 
, text3 text 
, text4 text 
, text5 text 
, text6 text 
); 

Вопрос:

Я пытаюсь запустить шаблон, соответствующий поиск на 6 текстовых столбцах с использованием оператора ~*. Можно ли запросить примерную таблицу по счету появления моего шаблона в 6 столбцах?

Пример:

Я хочу, чтобы найти все строки, которые сказали ключевое слово, по крайней мере 3 из 6 текстовых колонок. Какой из этих шести столбцов не имеет значения.

ответ

2

Вы можете найти количество совпадений в простой форме, как это:

insert into example values (1, 'a', 'a', 'a', 'b', 'c', 'd'); 

select 
    id, 
    (text1 ~* 'a')::int+ (text2 ~* 'a')::int+ 
    (text3 ~* 'a')::int+ (text4 ~* 'a')::int+ 
    (text5 ~* 'a')::int+ (text6 ~* 'a')::int as matches 
from example; 

id | matches 
----+--------- 
    1 |  3 

Если производительность не является ключевым вопросом в случае, вы можете использовать, может быть немного более удобным, но медленнее запрос:

select id, sum((t ~* 'a')::int) as matches 
from example, 
lateral unnest(array[text1, text2, text3, text4, text5, text6]) as t 
group by 1; 

Вы можете использовать выражение в WHERE (запрос # 1) или HAVING (запрос # 2) статей:

select * 
from example 
where 
    (text1 ~* 'a')::int+ (text2 ~* 'a')::int+ 
    (text3 ~* 'a')::int+ (text4 ~* 'a')::int+ 
    (text5 ~* 'a')::int+ (text6 ~* 'a')::int > 3; 

select e.* 
from example e, 
lateral unnest(array[text1, text2, text3, text4, text5, text6]) as t 
group by e.id 
having sum((t ~* 'a')::int) > 3; 
+0

Привет, спасибо вам ответить. Я не думаю, что мой вопрос обрисовал это, но я пытаюсь выбрать по минимальному счету. Поэтому в примерах, которые вы предоставили им, я не смог этого сделать. Я ищу запрос, где я могу сказать «где совпадения> 3» или что-то в этом роде. Любой способ изменить ваш запрос, чтобы отразить это? Я попытался, но немного вздрогнул. – user2737876

0

Как klin posted, но это должно быть проще и быстрее:

SELECT e.* 
FROM example e 
JOIN LATERAL (
    SELECT count(*) FILTER (WHERE x.t ~* 'keyword') AS ct 
    FROM (VALUES(text1), (text2), (text3), (text4), (text5), (text6)) x(t) 
    ) sub ON sub.ct >= 3; -- your minimum number of columns here 

О VALUES в LATERAL присоединиться:

О агрегатного FILTER:

Смежные вопросы