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))


Как правильно проверить это условие?

617   7  

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 (включая случай, когда массив имеет нулевые элементы). Результат является "ложным", если обнаружен какой-либо ложный результат.

not (3 = any(recipient_ids))?

обновление:

по состоянию на 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

    Ничего не найдено.