Postgres не в массиве
Я использую собственный тип массива 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))
Как правильно проверить это условие?
7 ответов:
SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))вы всегда можете свести на нет
WHERE (condition)СWHERE NOT (condition)
вы можете немного повернуть его и сказать "3 не равно всем идентификаторам":
where 3 != all (recipient_ids)9.21.4. Все (массив)
expression operator ALL (array expression)правая часть-это выражение в скобках, которое должно давать значение массива. Левое выражение вычисляется и сравнивается с каждым элементом массива с помощью заданного оператор, который должен давать логическое значение результат. Результат
ALLявляется "true", если все сравнения дают true (включая случай, когда массив имеет нулевые элементы). Результат является "ложным", если обнаружен какой-либо ложный результат.
обновление:
по состоянию на postgres 9.3,
можно использовать
NOTвместе с@>(оператор) чтобы достичь этого, а также.IE.
SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];
обратите внимание, что операторы 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)
остерегайтесь нулей
и
ALL:(some_value != ALL(some_array))и
ANY:NOT (some_value = ANY(some_array))будет работать до тех пор, как
some_arrayне null. Если массив может быть null, то вы должны учитывать его с помощью coalesce (), например(some_value != ALL(coalesce(some_array, array[]::int[])))или
NOT (some_value = ANY(coalesce(some_array, array[]::int[])))С docs:
если выражение массива дает нулевой массив, результатом любого будет null
если выражение выбора дает нулевой массив, результатом всего будет null
дополнения
ALL/ANYответыЯ предпочитаю все решения, использовать
allилиanyдля достижения результата, оценивая дополнительные примечания (например, о NULL s). Как еще одно дополнение, вот способ подумать об этих операторах.вы можете думать о них как операторы короткого замыкания:
all(array)проходит через все значения в массиве, сравнивая каждое с эталонным значением с помощью предоставляемых оператором. Как только сравнение даетfalse, процесс заканчивается на false, в противном случае true. (Сопоставимо с логическим замыканиемand.)any(array)проходит через все значения в массиве, сравнивая каждое с эталонным значением с помощью предоставленного оператора. Как только сравнение даетtrue, процесс заканчивается true, в противном случае false. (Сопоставимо с логическим замыканиемor.)вот почему
3 <> any('{1,2,3}')не дает желаемый результат: процесс сравнивает 3 с 1 для неравенства, которое истинно, и немедленно возвращает true. Одного значения в массиве, отличного от 3, достаточно, чтобы сделать все условие истинным. 3 в последней позиции массива возм. никогда не используемый.
3 <> all('{1,2,3}')С другой стороны гарантирует,все значения не равны 3. Он будет проходить через все сравнения, которые дают true до элемента, который дает false (последний в этом случае), чтобы вернуть false в качестве общего результат. Это то, чего хочет ОП.
Comments