Estou usando o tipo de array nativo do Postgres e tentando encontrar os registros onde o ID não está nos IDs de destinatário do array.
Posso descobrir onde eles estão em:
SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))
Mas isso não funciona:
SELECT COUNT(*) FROM messages WHERE (3 != ANY (recipient_ids))
SELECT COUNT(*) FROM messages WHERE (3 = NOT ANY (recipient_ids))
Qual é a maneira certa de testar essa condição?
arrays
postgresql
user577808
fonte
fonte
WHERE 3 NOT IN recipient_ids
o trabalho?text[]
eint[]
matriz:select not(array[1,2,3] @> array[3]);
null
coluna está contida ou não em um array, sempre dirá não. Levei cerca de 20 minutos depurando vários métodos de contenção para chegar à conclusão de que você não pode verificar se nulo está contido em um arrayRespostas:
Você sempre pode negar
WHERE (condition)
comWHERE NOT (condition)
fonte
ANY
vez deIN
conforme suarecipient_ids
lista de entrada crescer: stackoverflow.com/questions/1009706/…Você poderia inverter um pouco e dizer "3 não é igual a todos os IDs":
Do bom manual :
fonte
any
que não funciona neste casoany
eall
no documento do postgres, que diz: "x <> ANY (a,b,c)
é equivalente ax <> a OR <> b OR x <> c
". ref: postgresqltutorial.com/postgresql-any postgresqltutorial.com/postgresql-allAumentando as
ALL/ANY
respostasPrefiro todas as soluções que usam
all
ouany
que alcancem o resultado, valorizando as notas adicionais (por exemplo, sobre NULL s). Como outro acréscimo, aqui está uma maneira de pensar sobre esses operadores.Você pode pensar neles como operadores de curto-circuito :
all(array)
passa por todos os valores na matriz, comparando cada um com o valor de referência usando o operador fornecido. Assim que uma comparação resultafalse
, o processo termina com falso, caso contrário, verdadeiro. (Comparável ao lógico de curto-circuitoand
.)any(array)
passa por todos os valores na matriz, comparando cada um com o valor de referência usando o operador fornecido. Assim que uma comparação resultatrue
, o processo termina com verdadeiro, caso contrário, falso. (Comparável ao lógico de curto-circuitoor
.)É por isso
3 <> any('{1,2,3}')
que não produz o resultado desejado: o processo compara 3 com 1 para a desigualdade, o que é verdadeiro, e retorna imediatamente verdadeiro. Um único valor na matriz diferente de 3 é suficiente para tornar toda a condição verdadeira. O 3 na última posição da matriz é prob. nunca usado.3 <> all('{1,2,3}')
por outro lado, garante que todos os valores não sejam iguais a 3. Ele percorrerá todas as comparações que resultam em verdadeiro até um elemento que produz falso (o último neste caso), para retornar falso como o resultado geral. É isso que o OP deseja.fonte
not (3 = any(recipient_ids))
?fonte
3 <> ANY(ARRAY[1,2,3,4])
. Deveria ter funcionado assim: \uma atualização:
a partir do postgres 9.3,
você pode usar
NOT
em conjunto com o@>
operador (contém) para fazer isso também.IE.
SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];
fonte
Cuidado com os NULLs
Ambos
ALL
:E
ANY
:Funcionaria, desde que
some_array
não seja nulo. Se a matriz pode ser nula, você deve contabilizá-la com coalesce (), por exemploOu
Dos documentos :
fonte
Observe que os operadores ANY / ALL não funcionarão com índices de matriz. Se os índices estão em mente:
e o negativo:
Um índice pode então ser criado como:
fonte
&&
SELECT COUNT(*) FROM "messages" WHERE ARRAY[3] && recipient_ids
.