Использование предложения where в сочетании с подзапросом, результатом которого является запись, содержащая массив

#postgresql #postgresql-10

#postgresql #postgresql-10

Вопрос:

Я нашел некоторые результаты / ответы, касающиеся поиска в массиве, но:

  1. WHERE = ANY работает со столбцом, но не с subquery который возвращает одну запись, содержащую массив в результате, вызывает ошибку
  2. WHERE IN также вызывает ту же ошибку
  3. Я также протестировал untest в подзапросе ошибку, аналогичную первым 2
  4. Я не хочу проверять, находится ли значение в массиве, но получаю / выполняю запрос для значений в массиве, как WHERE IN (1,2,3,4) , а не как в других вопросах / ответах

Ошибка:

Ни один оператор не соответствует заданному имени и типам аргументов. Возможно, вам потребуется добавить явные приведения типов.

или

Ни один оператор не соответствует int = int[]

path — это int[] тип массива.

Структура:

 id | name |  | slug   | path | parent_id
1    name1     slug1     {1}      null
2    name2     slug2    {1,2}     1
3    name3     slug3   {1,2,3}    2
4    nam4      slug4   {4}       null
  

Что я пытаюсь использовать в качестве основы:

 SELECT t.id, t.name, t.slug FROM types AS t
WHERE t.id in (SELECT t.path FROM types AS t WHERE t.id = 24)
ORDER BY depth ASC
  

В основном path похож на breadcrumb , {grandparent,parent,type}

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

1. Сначала вы должны использовать разные сочетания клавиш для основного запроса и подзапроса, по крайней мере, дважды использовать t сложно для чтения. Во-вторых, поскольку ANY работает со столбцом, попробуйте записать его как inner join

Ответ №1:

Вот одно из них, использующее IN и unnest()

 SELECT t1.id,
       t1."name",
       t1.slug
       FROM types t1
       WHERE t1.id IN (SELECT un.e
                              FROM types t2
                                   CROSS JOIN LATERAL unnest(t2.path) un (e)
                              WHERE t2.id = 2)
       ORDER BY array_length(t1.path, 1);
  

А другой, использующий массив, содержится в operator <@ .

 SELECT t1.id,
       t1."name",
       t1.slug
       FROM types t1
       WHERE ARRAY[t1.id] <@ (SELECT t2.path
                                     FROM types t2
                                          WHERE t2.id = 2)
       ORDER BY array_length(t1.path, 1);
  

И одно использование = ANY .

 SELECT t1.id,
       t1."name",
       t1.slug
       FROM types t1
       WHERE t1.id = ANY ((SELECT t2.path
                                  FROM types t2
                                  WHERE t2.id = 2)::integer[])
       ORDER BY array_length(t1.path, 1);
  

db<>скрипта

Вы не включили depth в свой образец данных, поэтому я заменил его на array_length(t1.path, 1) , что, вероятно, и есть.