Postgres dizide DEĞİL


101

Postgres'in yerel dizi türünü kullanıyorum ve kimliğin dizi alıcı kimlikleri içinde olmadığı kayıtları bulmaya çalışıyorum.

Nerede olduklarını bulabilirim:

SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))

Ama bu işe yaramıyor:

SELECT COUNT(*) FROM messages WHERE (3 != ANY (recipient_ids))
SELECT COUNT(*) FROM messages WHERE (3  = NOT ANY (recipient_ids))

Bu durumu test etmenin doğru yolu nedir?


does WHERE 3 NOT IN recipient_idsişi?
Janus Troelsen

1
İlgili not: text[]ve int[]dizi:select not(array[1,2,3] @> array[3]);
Steve Peak

3
Uzman ipucu: Bir nullsütunun bir dizide yer alıp almadığını kontrol ediyorsanız , her zaman hayır diyecektir. Bir dizide null
André Pena

Yanıtlar:



41

Bunu biraz değiştirebilir ve "3 tüm kimliklere eşit değildir" diyebilirsiniz:

where 3 != all (recipient_ids)

Gönderen ince kılavuzu :

9.21.4. TÜM (dizi)

expression operator ALL (array expression)

Sağ taraf, bir dizi değeri vermesi gereken parantezli bir ifadedir. Sol taraftaki ifade değerlendirilir ve verilen operatör kullanılarak dizinin her bir öğesi ile karşılaştırılır , bu da bir Boole sonucu vermelidir. ALLTüm karşılaştırmalar true değerini verirse sonucu "true" olur (dizinin sıfır öğeye sahip olduğu durum dahil). Herhangi bir yanlış sonuç bulunursa sonuç "yanlıştır".


bu gerçekten neden anybu durumda işe yaramadığını açıklamıyor
seanlinsley

Nedeni doğru bir şekilde açıkladığı için bu kabul edilmelidir. PS da bulabilirsiniz anyve alldiyor postgres doküman üzerinde: " x <> ANY (a,b,c) eşdeğerdir x <> a OR <> b OR x <> c". ref: postgresqltutorial.com/postgresql-any postgresqltutorial.com/postgresql-all
Tyler Temp

19

ALL/ANYCevapları Artırmak

Ek notları takdir ederek (örneğin NULL'lar hakkında ) sonucu kullanan allveya anysonucu elde eden tüm çözümleri tercih ederim . Başka bir genişletme olarak, işte bu operatörler hakkında düşünmenin bir yolu.

Bunları kısa devre operatörleri olarak düşünebilirsiniz :

  • all(array)sağlanan operatörü kullanarak her birini referans değerle karşılaştırarak dizideki tüm değerleri gözden geçirir. Bir karşılaştırma falsesonuç verir vermez , süreç yanlış ile biter, aksi takdirde doğru. (Kısa devre mantıksal ile karşılaştırılabilir and.)
  • any(array)sağlanan operatörü kullanarak her birini referans değerle karşılaştırarak dizideki tüm değerleri gözden geçirir. Bir karşılaştırma truesonuç verir vermez süreç true ile biter, aksi takdirde false. (Kısa devre mantıksal ile karşılaştırılabilir or.)

Bu yüzden 3 <> any('{1,2,3}')istenen sonucu vermiyor: İşlem, eşitsizlik için 3'ü 1 ile karşılaştırır, bu doğrudur ve hemen doğru döndürür. Dizideki 3'ten farklı tek bir değer, koşulun tamamını doğru yapmak için yeterlidir. Son dizi konumundaki 3, probdur. Hiç kullanılmamış.

3 <> all('{1,2,3}')diğer yandan tüm değerlerin eşit olmadığından emin olur 3. Genel sonuç olarak yanlış döndürmek için, yanlış (bu durumda sonuncusu) veren bir öğeye kadar doğru sonuç veren tüm karşılaştırmalar boyunca çalışır. OP'nin istediği bu.


12

not (3 = any(recipient_ids))?


Teşekkürler, kullanıyordum 3 <> ANY(ARRAY[1,2,3,4]). Şu şekilde çalışmalıydı: \
yeyo

12

bir güncelleme:

postgres 9.3 itibariyle,

bunu başarmak NOTiçin @> (operatörü içerir) ile birlikte kullanabilirsiniz .

IE.

SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];


12

NULL'lara dikkat edin

İkisi de ALL:

(some_value != ALL(some_array))

Ve ANY:

NOT (some_value = ANY(some_array))

some_arrayBoş olmadığı sürece çalışır . Dizi boş olabilirse, bunu coalesce () ile hesaba katmalısınız, örneğin

(some_value != ALL(coalesce(some_array, array[]::int[])))

Veya

NOT (some_value = ANY(coalesce(some_array, array[]::int[])))

Gönderen docs :

Dizi ifadesi boş bir dizi verirse, ANY'nin sonucu boş olur

Dizi ifadesi boş bir dizi verirse, ALL'nin sonucu boş olur


3

ANY / ALL operatörlerinin dizi dizinleriyle çalışmayacağını unutmayın. Dizinler aklınızda ise:

SELECT COUNT(*) FROM "messages" WHERE 3 && recipient_ids

ve olumsuz:

SELECT COUNT(*) FROM "messages" WHERE NOT (3 && recipient_ids)

Daha sonra aşağıdaki gibi bir dizin oluşturulabilir:

CREATE INDEX recipient_ids_idx on tableName USING GIN(recipient_ids)

Diğer cevaplardan farklı olarak, bu cevap aslında PostgreSQL dizisi örtüşme operatörünü kullanır. &&
Tavan Gecko

6
Bu yazıldığı gibi çalışmayacak. && ve @> gibi dizi operatörleri, her iki öğenin de dizi olmasını gerektirir, ancak 3 bu değildir. İşe Bunun için, sorgu olarak yazılmış olması gerekir: SELECT COUNT(*) FROM "messages" WHERE ARRAY[3] && recipient_ids.
Dologan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.