Namun varian kedua masing-masing tidak setara dengan yang lain. Varian kedua dari ANYkonstruksi tersebut mengambil sebuah larik (harus berupa jenis larik sebenarnya), sedangkan varian kedua dari INmengambil daftar nilai yang dipisahkan koma . Ini mengarah pada batasan yang berbeda dalam meneruskan nilai dan juga dapat mengarah ke rencana kueri yang berbeda dalam kasus khusus:
"Temukan baris di mana iddalam larik yang diberikan":
SELECT*FROM tbl WHERE id =ANY(ARRAY[1,2]);
Pembalikan: "Temukan baris idyang tidak ada dalam array":
SELECT*FROM tbl WHERE id <>ALL(ARRAY[1,2]);SELECT*FROM tbl WHERE id <>ALL('{1, 2}');-- equivalent array literalSELECT*FROM tbl WHERENOT(id =ANY('{1, 2}'));
Ketiganya setara. Yang pertama dengan konstruktor array , dua lainnya dengan literal array . Tipe data dapat diturunkan dari konteks dengan jelas. Lain, pemeran eksplisit mungkin diperlukan, seperti '{1,2}'::int[].
Baris dengan id IS NULLtidak lulus salah satu ekspresi ini. Untuk memasukkan NULLnilai - nilai tambahan:
Sebaiknya klarifikasi secara eksplisit bahwa hasil varian kedua akan selalu sama. Saya 99% yakin bahwa kenyataannya memang demikian, tetapi jawabannya tampaknya tidak menyatakannya. Artinya, SELECT * from mytable where id in (1, 2, 3)akan selalu menghasilkan baris yang sama dengan SELECT * from mytable where id = ANY('{1, 2, 3}'), meskipun mungkin memiliki rencana kueri yang berbeda.
KPD
1
ANYtidak bisa digabungkan dengan !=operator. Saya tidak berpikir itu didokumentasikan, tetapi select * from foo where id != ANY (ARRAY[1, 2])tidak sama dengan select * from foo where id NOT IN (1, 2). Di sisi lain, select * from foo where NOT (id = ANY (ARRAY[1, 2]))berfungsi seperti yang diharapkan.
qris
1
@qris: ANYdapat digabungkan dengan !=operator. Tapi ada lebih banyak lagi mengenai hal tersebut. Saya menambahkan bab di atas. (Perhatikan bahwa <>operator dalam SQL standar - meskipun !=diterima juga di Postgres.)
Erwin Brandstetter
Bagaimana cara kerja versi terakhir yang menyertakan NULLnilai? Apakah akan WHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;berhasil dengan baik?
dvtan
1
@dvtan: (id = ...) IS NOT TRUEberfungsi karena id = ...hanya mengevaluasi TRUEjika ada kecocokan aktual. Hasil FALSEatau NULLlulus ujian kami. Lihat: stackoverflow.com/a/23767625/939860 . Ekspresi yang Anda tambahkan menguji sesuatu yang lain. Ini akan setaraWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Erwin Brandstetter
3
Ada dua poin yang jelas, serta poin-poin dalam jawaban lainnya:
Jawaban:
(Bukan
IN
jugaANY
"operator". Sebuah "konstruksi" atau "elemen sintaks".)Logikanya , mengutip manual :
Tapi ada dua varian sintaks dari
IN
dan dua varianANY
. Rincian:IN
mengambil satu set sama dengan= ANY
mengambil satu set , seperti yang ditunjukkan di sini:Namun varian kedua masing-masing tidak setara dengan yang lain. Varian kedua dari
ANY
konstruksi tersebut mengambil sebuah larik (harus berupa jenis larik sebenarnya), sedangkan varian kedua dariIN
mengambil daftar nilai yang dipisahkan koma . Ini mengarah pada batasan yang berbeda dalam meneruskan nilai dan juga dapat mengarah ke rencana kueri yang berbeda dalam kasus khusus:=any()
tetapi digunakan denganin
ANY
lebih serbagunaThe
ANY
membangun jauh lebih fleksibel, karena dapat dikombinasikan dengan berbagai operator, tidak hanya=
. Contoh:Untuk sejumlah besar nilai, memberikan satu set skala yang lebih baik untuk masing-masing:
Terkait:
Pembalikan / kebalikan / pengecualian
"Temukan baris di mana
id
dalam larik yang diberikan":Pembalikan: "Temukan baris
id
yang tidak ada dalam array":Ketiganya setara. Yang pertama dengan konstruktor array , dua lainnya dengan literal array . Tipe data dapat diturunkan dari konteks dengan jelas. Lain, pemeran eksplisit mungkin diperlukan, seperti
'{1,2}'::int[]
.Baris dengan
id IS NULL
tidak lulus salah satu ekspresi ini. Untuk memasukkanNULL
nilai - nilai tambahan:sumber
SELECT * from mytable where id in (1, 2, 3)
akan selalu menghasilkan baris yang sama denganSELECT * from mytable where id = ANY('{1, 2, 3}')
, meskipun mungkin memiliki rencana kueri yang berbeda.ANY
tidak bisa digabungkan dengan!=
operator. Saya tidak berpikir itu didokumentasikan, tetapiselect * from foo where id != ANY (ARRAY[1, 2])
tidak sama denganselect * from foo where id NOT IN (1, 2)
. Di sisi lain,select * from foo where NOT (id = ANY (ARRAY[1, 2]))
berfungsi seperti yang diharapkan.ANY
dapat digabungkan dengan!=
operator. Tapi ada lebih banyak lagi mengenai hal tersebut. Saya menambahkan bab di atas. (Perhatikan bahwa<>
operator dalam SQL standar - meskipun!=
diterima juga di Postgres.)NULL
nilai? Apakah akanWHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;
berhasil dengan baik?(id = ...) IS NOT TRUE
berfungsi karenaid = ...
hanya mengevaluasiTRUE
jika ada kecocokan aktual. HasilFALSE
atauNULL
lulus ujian kami. Lihat: stackoverflow.com/a/23767625/939860 . Ekspresi yang Anda tambahkan menguji sesuatu yang lain. Ini akan setaraWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Ada dua poin yang jelas, serta poin-poin dalam jawaban lainnya:
Mereka sama persis saat menggunakan sub queri:
Di samping itu:
Hanya
IN
operator yang mengizinkan daftar sederhana:Menganggap mereka persis sama telah membuat saya beberapa kali lupa bahwa
ANY
tidak bekerja dengan daftar.sumber