Сложный поиск Postgres sql в текстовом массиве по любому значению из текстового массива - PullRequest
0 голосов
/ 07 августа 2020

так вот моя проблема - заставить запрос работать, это очень сложно сделать, я использовал unnest, поиск с использованием @>, ничего не работает.

У меня есть таблица в db у которого есть поле text[], и я передаю поле text[] функции, чтобы любое из значений из него возвращало строку, или, если я не передаю значение, оно должно возвращать их все. Например:

таблица:

id (int)
names (text[])

данные в БД:

id   names
---------------------------------
1    { alex }
2    { tom, john }
3    { tom, alex }
4    { rocky, simon, leon, john }

как это должно работать?

  • когда я прохожу {simon} он должен возвращать только строку 4
  • , когда я передаю {alex}, он должен возвращать строки 1 и 3
  • , когда я передаю {tom,leon}, он должен возвращать строки 2, 3 и 4
  • когда я передаю значение null, он должен возвращать строки 1,2,3,4
  • любой параметр in, который соответствует любому значению из строки, должен возвращать строку
CREATE OR REPLACE FUNCTION public.get_names
(
    _names TEXT[]
)
RETURNS JSONB
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
    RETURN (SELECT
        json_agg(t)
    FROM
        (
            SELECT
                n.id,
                n.names
            FROM
                public.names n
            WHERE
               _names IS NULL 
               OR exists (select unnest(cast(_names as text[]))) = ANY (n.names)
        ) t);
END;
$BODY$;

Мне не удалось выполнить ни один из моих запросов с ошибками, например:

  • оператор не существует: boolean = символ меняется
  • ЛЮБОЙ / ALL (массив) не поддерживает набор аргументов
  • Более одной строки, возвращаемой подзапросом, используемым в качестве выражения
  • и более ..

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

Ответы [ 2 ]

0 голосов
/ 07 августа 2020

перекрывает оператор && будет делать то, что вы хотите

select *
from test
where names && array['tom', 'leon']

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

Чтобы иметь дело с параметром NULL, вы можете использовать NULL проверку в своей функции

CREATE OR REPLACE FUNCTION public.get_names (_names TEXT[] default null )
  RETURNS JSONB
LANGUAGE sql
AS 
$BODY$
  SELECT jsonb_agg(t)
  FROM (
    SELECT n.id, n.names
    FROM public.test n
    WHERE _names is null 
      OR n.names && _names 
  ) t;
$BODY$;
0 голосов
/ 07 августа 2020

Напишите свою функцию таким образом, используя оператор &&:

CREATE OR REPLACE FUNCTION public.get_names (_names TEXT[] default null )
RETURNS JSONB
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
    RETURN 
    
    (SELECT
        json_agg(t)
    FROM
        (
            SELECT
                id,
                names
            FROM
                public.test n
            WHERE
                case 
                when _names IS not NULL then names && _names 
                else 1=1
                end
        ) t);
END;
$BODY$;

DEMO

...