Поиск массива Postgres в предложении WHERE - PullRequest
10 голосов
/ 30 марта 2011

У меня есть запрос:

SELECT bar, (SELECT name FROM names WHERE value = bar) as name
FROM foobar WHERE foo = 1 and bar = ANY (1,2,3)

Моя проблема в том, что когда в таблице foobar нет строки, содержащей bar = 3 (или какое-либо другое запрашиваемое значение), строки для этого значения бара не возвращаются.

Я бы хотел, чтобы мой запрос вместо этого возвратил строку [bar, NULL], но не могу придумать, как это сделать.

Это вообще возможно?

Ответы [ 3 ]

14 голосов
/ 31 марта 2011

Возможно, вам нужен такой подход:

обкатка:

create view names as 
select 1 as value, 'Adam' as name union all select 2, 'Beth';

create view foobar as 
select 1 as foo, 1 as bar union all select 1, 2;

оригинальный метод:

select bar, (select name from names where value = bar) as name 
from foobar 
where foo = 1 and bar = any (array[1, 2, 3]);

 bar | name
-----+------
   1 | Adam
   2 | Beth
(2 rows)

альтернативный метод:

with w as (select unnest(array[1, 2, 3]) as bar)
select bar, (select name from names where value = bar) as name
from w left outer join foobar using(bar);

 bar | name
-----+------
   1 | Adam
   2 | Beth
   3 |
(3 rows)

Если вы используете 8.3 или более раннюю версию, встроенной функции unnest нет, но вы можете выполнить собственную (не очень эффективную) замену:

create or replace function unnest(anyarray) returns setof anyelement as $$
  select $1[i] from generate_series(array_lower($1,1), array_upper($1,1)) i;
$$ language 'sql' immutable;
1 голос
/ 31 марта 2011
SELECT  vals.bar, name
FROM    (
        SELECT  *
        FROM    unnest([1, 2, 3]) AS bar
        ) vals
LEFT JOIN
        foobar
ON      foobar.foo = 1
        AND foobar.bar = vals.bar
LEFT JOIN
        names
ON      names.value = vals.bar
1 голос
/ 31 марта 2011
SELECT bar, name
FROM foobar
INNER JOIN names ON foobar.bar = names.value
WHERE foo = 1 and bar = ANY (1,2,3)

Попробуйте вместо этого запрос.

...