Używam rodzimego typu tablicy Postgres i próbuję znaleźć rekordy, w których identyfikator nie znajduje się w identyfikatorach odbiorców tablicy.
Mogę znaleźć, gdzie się znajdują:
SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))
Ale to nie działa:
SELECT COUNT(*) FROM messages WHERE (3 != ANY (recipient_ids))
SELECT COUNT(*) FROM messages WHERE (3 = NOT ANY (recipient_ids))
Jaki jest właściwy sposób sprawdzenia tego stanu?
arrays
postgresql
user577808
źródło
źródło
WHERE 3 NOT IN recipient_ids
działa?text[]
iint[]
tablica:select not(array[1,2,3] @> array[3]);
null
kolumna jest zawarta w tablicy, czy nie, zawsze powie nie. Zajęło mi około 20 minut debugowania kilku metod zawierających elementy, aby dojść do wniosku, że nie można sprawdzić, czy w tablicy znajduje się wartość nullOdpowiedzi:
SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))
Zawsze można negować
WHERE (condition)
zWHERE NOT (condition)
źródło
ANY
zamiast wIN
miaręrecipient_ids
wzrostu listy danych wejściowych: stackoverflow.com/questions/1009706/ ...Możesz to trochę odwrócić i powiedzieć „3 nie jest równe wszystkim identyfikatorom”:
Z dobrej instrukcji :
źródło
any
nie działa w tym przypadkuany
iall
na postgres doc, który mówi: "x <> ANY (a,b,c)
jest równoważnex <> a OR <> b OR x <> c
". ref: postgresqltutorial.com/postgresql-any postgresqltutorial.com/postgresql-allRozszerzanie
ALL/ANY
odpowiedziPreferuję wszystkie rozwiązania, które wykorzystują
all
lubany
osiągają wynik, ceniąc sobie dodatkowe uwagi (np. O NULL- ach). Jako kolejne ulepszenie, oto sposób myślenia o tych operatorach.Można o nich myśleć jako o operatorach zwarć :
all(array)
przechodzi przez wszystkie wartości w tablicy, porównując każdą z wartością odniesienia przy użyciu podanego operatora. Gdy tylko wyniki porównania wypadnąfalse
, proces kończy się błędem, w przeciwnym razie prawdą. (Porównywalne z logiką zwarciowąand
.)any(array)
przechodzi przez wszystkie wartości w tablicy, porównując każdą z wartością odniesienia przy użyciu podanego operatora. Gdy tylko wynik porównaniatrue
zakończy się, proces kończy się na prawdzie, w przeciwnym razie na fałszu. (Porównywalne z logiką zwarciowąor
.)Dlatego
3 <> any('{1,2,3}')
nie daje pożądanego wyniku: proces porównuje 3 z 1 pod względem nierówności, co jest prawdą, i natychmiast zwraca prawdę. Pojedyncza wartość w tablicy różna od 3 wystarczy, aby spełnić cały warunek. 3 na ostatniej pozycji tablicy to prawdop. nigdy nie używany.3 <> all('{1,2,3}')
z drugiej strony upewnia się, że wszystkie wartości nie są równe 3. Przeszedł przez wszystkie porównania, które dały prawdę, aż do elementu, który daje fałsz (ostatni w tym przypadku), aby zwrócić false jako wynik ogólny. Tego właśnie chce PO.źródło
not (3 = any(recipient_ids))
?źródło
3 <> ANY(ARRAY[1,2,3,4])
. Powinno działać w ten sposób: \aktualizacja:
od postgres 9.3,
możesz użyć
NOT
w tandemie z@>
(zawiera operator), aby to osiągnąć.TO ZNACZY.
SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];
źródło
Uważaj na wartości NULL
Obie
ALL
:Oraz
ANY
:Działa, o ile
some_array
nie jest zerowa. Jeśli tablica może być pusta, to należy ją uwzględnić za pomocą coalesce (), npLub
Z dokumentów :
źródło
Zauważ, że operatory ANY / ALL nie będą działać z indeksami tablicowymi. Jeśli chodzi o indeksy:
SELECT COUNT(*) FROM "messages" WHERE 3 && recipient_ids
i negatywne:
SELECT COUNT(*) FROM "messages" WHERE NOT (3 && recipient_ids)
Następnie można utworzyć indeks, taki jak:
CREATE INDEX recipient_ids_idx on tableName USING GIN(recipient_ids)
źródło
&&
SELECT COUNT(*) FROM "messages" WHERE ARRAY[3] && recipient_ids
.