Я использую собственный тип массива Postgres и пытаюсь найти записи, идентификатор которых отсутствует в идентификаторах получателей массива.
Я могу найти, где они В:
SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))
Но это не работает:
SELECT COUNT(*) FROM messages WHERE (3 != ANY (recipient_ids))
SELECT COUNT(*) FROM messages WHERE (3 = NOT ANY (recipient_ids))
Как правильно проверить это состояние?
arrays
postgresql
user577808
источник
источник
WHERE 3 NOT IN recipient_ids
работу?text[]
andint[]
array:select not(array[1,2,3] @> array[3]);
null
столбец в массиве или нет, он всегда скажет «нет». Мне потребовалось около 20 минут отладки нескольких содержащих методов, чтобы прийти к выводу, что вы не можете проверить, содержится ли null в массивеОтветы:
SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))
Вы всегда можете свести на нет
WHERE (condition)
сWHERE NOT (condition)
источник
ANY
а не поIN
мереrecipient_ids
роста вашего входного списка: stackoverflow.com/questions/1009706/…Вы можете немного перевернуть его и сказать "3 не равно всем идентификаторам":
Из прекрасного руководства :
источник
any
в данном случае не работаетany
иall
в postgres doc, где написано: «x <> ANY (a,b,c)
эквивалентноx <> a OR <> b OR x <> c
». Ссылка: postgresqltutorial.com/postgresql-any postgresqltutorial.com/postgresql-allДополнение
ALL/ANY
ответовЯ предпочитаю все решения, которые используют
all
илиany
для достижения результата, принимая во внимание дополнительные примечания (например, о NULL ). В качестве еще одного дополнения, вот способ подумать об этих операторах.Вы можете думать о них как об операторах короткого замыкания :
all(array)
перебирает все значения в массиве, сравнивая каждое с эталонным значением с помощью предоставленного оператора. Как только сравнениеfalse
завершается, процесс завершается ложью, в противном случае - истинным. (Сравнимо с логикой короткого замыканияand
.)any(array)
перебирает все значения в массиве, сравнивая каждое с эталонным значением с помощью предоставленного оператора. Как только сравнениеtrue
завершается, процесс завершается истинным, в противном случае - ложным. (Сравнимо с логикой короткого замыканияor
.)Вот почему
3 <> any('{1,2,3}')
не дает желаемого результата: процесс сравнивает 3 с 1 на предмет неравенства, что верно, и немедленно возвращает истину. Единственного значения в массиве, отличного от 3, достаточно, чтобы выполнить все условие. Число 3 в последней позиции массива - это вероятность. никогда не использовался.3 <> all('{1,2,3}')
с другой стороны, гарантирует, что все значения не равны 3. Он будет проходить через все сравнения, которые дают true, до элемента, который дает false (последний в этом случае), чтобы вернуть false в качестве общего результата. Это то, чего хочет ОП.источник
not (3 = any(recipient_ids))
?источник
3 <> ANY(ARRAY[1,2,3,4])
. Это должно было работать таким образом: \обновление:
начиная с postgres 9.3,
вы также можете использовать
NOT
в тандеме с@>
оператором (contains), чтобы добиться этого.IE.
SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];
источник
Остерегайтесь NULL
Оба
ALL
:И
ANY
:Будет работать, пока
some_array
не равно нулю. Если массив может быть нулевым, вы должны учесть его с помощью coalesce (), напримерИли
Из документов :
источник
Обратите внимание, что операторы ANY / ALL не работают с индексами массива. Если имеются в виду индексы:
SELECT COUNT(*) FROM "messages" WHERE 3 && recipient_ids
и отрицательный:
SELECT COUNT(*) FROM "messages" WHERE NOT (3 && recipient_ids)
Затем можно создать индекс, например:
CREATE INDEX recipient_ids_idx on tableName USING GIN(recipient_ids)
источник
&&
SELECT COUNT(*) FROM "messages" WHERE ARRAY[3] && recipient_ids
.