2014-09-01 3 views
11

Я часто использовал синтаксис integer = ANY(integer[]), но теперь оператор ANY не работает. Это первый раз, когда я использую его для сравнения скаляра с целым числом, возвращаемым из CTE, но я думал, что это не должно вызывать проблем.Оператор не существует: integer = integer [] в запросе с ANY

Мой запрос:

WITH bar AS (
    SELECT array_agg(b) AS bs 
    FROM foo 
    WHERE c < 3 
) 
SELECT a FROM foo WHERE b = ANY (SELECT bs FROM bar); 

Когда я бегу, он бросает следующее сообщение об ошибке:

ERROR: operator does not exist: integer = integer[]: WITH bar AS ( SELECT array_agg(b) AS bs FROM foo WHERE c < 3) SELECT a FROM foo WHERE b = ANY (SELECT bs FROM bar)

Подробности в этом SQL Fiddle.

Так что я делаю неправильно?

ответ

11

На основании части operator does not exist: integer = integer[] сообщения об ошибке, то оказывается, что bs колонка должна быть unnest-е изд, чтобы получить правую часть обратно в integer поэтому оператор сравнения можно найти:

WITH bar AS (
    SELECT array_agg(b) AS bs 
    FROM foo 
    WHERE c < 3 
) 
SELECT a 
FROM foo 
WHERE b = ANY (SELECT unnest(bs) FROM bar); 

Это приводит к выходу:

A 
2 
3 

Учитывая документ для ANY function:

The right-hand side is a parenthesized subquery, which must return exactly one column. The left-hand expression is evaluated and compared to each row of the subquery result using the given operator, which must yield a Boolean result. The result of ANY is "true" if any true result is obtained. The result is "false" if no true result is found (including the case where the subquery returns no rows).

... ошибка имеет смысл, так как выражение левого является integer - колонка b - в то время как выражение правого представляет собой массив integer с или integer[], и поэтому сравнение заканчивается имеет вид integer = integer[], который не имеет оператора и, следовательно, приводит к ошибке.

unnest Значение integer[] составляет левое и правое выражения integer s, поэтому сравнение может продолжаться.

Изменено SQL Fiddle.

Примечание: такое же поведение наблюдается при использовании IN вместо = ANY.

+8

Дополнительное объяснение, основанное на ваш ответ: Потому что '1 = ANY (ARRAY [1,2,3])' является законным, то разумно ожидать также '1 = ANY (SELECT ARRAY [1,2,3]) ', чтобы быть законным, но это не потому, что это создало бы двусмысленность относительно того, хотите ли вы' 1 = ARRAY [1,2,3] 'или' 1 = 1 OR 1 = 2 OR 1 = 3', и анализатор недостаточно умен, чтобы понять, что только один может быть законным. Вы можете сказать, что вам действительно нужна форма массива-ЛЮБОЙ с '1 = ЛЮБОЙ ((SELECT ARRAY [1,2,3]) :: int [])' (который я бы сделал вместо 'unsest'ing). –

+0

Ах, интересно.Спасибо за дополнительную информацию. – khampson

+0

@CraigRinger: спасибо! Ответ Кена помог мне, как это сделать правильно, но ваш комментарий заставил меня понять, почему мой запрос был неправильным. –

0

колонна должна быть unnest

С панели AS ( ВЫБОР array_agg (б) в качестве базовой станции ИЗ Foo где С) выбрать ОТ Foo где В = ANY (SELECT unnest (bs) FROM bar);

+1

Как это отличается от существующего ответа? –

0

без unnest

WITH bar AS (
    SELECT array_agg(b) AS bs 
    FROM foo 
    WHERE c < 3 
) 
SELECT a FROM foo WHERE (SELECT b = ANY (bs) FROM bar); 
Смежные вопросы