Минимум два перекрытия Postgres в массиве

#arrays #postgresql

#массивы #postgresql

Вопрос:

Мне нужно выполнить поиск в большой таблице (более 100 миллионов записей), используя довольно сложный набор правил.

В настоящее время у меня есть таблица, которая выглядит следующим образом

 CREATE TABLE equipment (
     id serial primary key,
     description varchar,
     code integer,
     tags varchar[]
)
 

И мне нужно выполнить запрос на основе

1) Определенный список кодов (ГДЕ код В (1,4,5,8)

2) Массив тегов, которых НЕТ в массиве тегов

3) Массив тегов, которые находятся В массиве тегов, но должны присутствовать как минимум два

 SELECT * FROM equipment WHERE 
    code IN (1,3,6,7,8) 
    AND NOT ('{sports, outdoors, camping}' amp;amp; tags)
    AND ('{tennis, squash, badminton, volleyball}' amp;amp; tags)
 

Но я не знаю, как сделать так, чтобы по крайней мере два значения (теннис, сквош, бадминтон, волейбол) перекрывали массив тегов.

Я использую Postgres 10.6

Ответ №1:

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

 SELECT e.*
FROM equipment e
WHERE code IN (1,3,6,7,8) 
  AND NOT ('{sports, outdoors, camping}' amp;amp; tags)
  AND EXISTS (SELECT 1
              FROM unnest(e.tags) x(tg)
              WHERE x.tg = any ('{tennis, squash, badminton, volleyball}')
              HAVING count(*) >= 2);
 

Если у вас есть индекс в tags столбце, тогда И (‘{теннис, сквош, бадминтон, волейбол}’ amp;amp; теги) сохраняют ваше текущее состояние:

 AND ('{tennis, squash, badminton, volleyball}' amp;amp; tags)
 

может повысить производительность, поскольку это должно предотвратить отмену вложенности тегов для строк, в которых изначально не было найдено совпадений.

Комментарии:

1. Потрясающе, большое спасибо. И да, у меня был индекс GIN в тегах, так что дополнительные И помогли