Postgresql Text Array получить строки НЕ КАК определенное значение? - PullRequest
0 голосов
/ 29 мая 2018

Допустим, у меня есть простая таблица, такая как эта:

id_ | tags
---------------
0   | foo1, baz
1   | bar1, qux

Столбец id_ имеет тип SERIAL, а столбец tags имеет тип TEXT[] (текстовый массив).

Для поиска в столбце tags с оператором LIKE я использую комбинацию unnest и DISTINCT ON, например:

SELECT DISTINCT ON (id_) *
FROM (
  SELECT unnest(tags) tag, *
  FROM Records
) x
WHERE
  (tag LIKE '%o%');

Это прекрасно работает,Запрос возвращает строку 0, как и должно быть.

Теперь я пытаюсь найти способ инвертировать запрос, чтобы он возвращал только строки, которые не соответствуютLIKE выражение.Я пытался с этим:

WHERE
  (tag NOT LIKE '%o%');

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

Я также пробовал с подзапросами, например, такими:

    WHERE
      (x.id_ NOT IN (SELECT id_ FROM Records WHERE tag like '%o%'));

Но он по-прежнему возвращает обе строки.

Кто-нибудь знает, как это можно исправить?

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Вы можете использовать ALL, чтобы проверить, что все неопубликованные теги равны NOT LIKE '%o%', используя возможность Postgres возвращать логические значения для выражений сравнения.

SELECT DISTINCT ON (id_) *
       FROM records
       WHERE true = ALL (SELECT tag NOT LIKE '%o%'
                                FROM unnest(tags) tag);

Если один тег равен LIKE '%o', NOT LIKE '%o%' вернет false для этого тега и больше не будут все выбранные значения true, что необходимо для true = ALL (...), чтобы быть true.

Кстати, вы также можете легко отрицать это, используя ANY и LIKE вместо:

SELECT DISTINCT ON (id_) *
       FROM records
       WHERE true = ANY (SELECT tag LIKE '%o%'
                                FROM unnest(tags) tag);

(или, возможно, других комбинаций true или false, = ALL или = ANY, (SELECT tag LIKE ...) или (SELECT tag NOT LIKE ...))

SQL Fiddle

0 голосов
/ 29 мая 2018

like должен соответствовать только одному тегу.not like должно соответствовать всем из них.Следовательно, агрегация:

SELECT id_
FROM (SELECT unnest(tags) tag, *
      FROM Records
     ) x
GROUP BY id_
HAVING SUM( (tag LIKE '%o%')::int) = 0;

Или используйте bool_and():

HAVING bool_and( (tag LIKE '%o%')::int);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...