Saya punya query SQL sederhana di PostgreSQL 8.3 yang mengambil banyak komentar. Saya memberikan daftar nilai yang diurutkan ke IN
konstruk dalam WHERE
klausa:
SELECT * FROM comments WHERE (comments.id IN (1,3,2,4));
Ini mengembalikan komentar dalam urutan acak yang kebetulan seperti id 1,2,3,4
.
Saya ingin baris yang dihasilkan diurutkan seperti daftar di IN
konstruk: (1,3,2,4)
.
Bagaimana cara mencapainya?
sql
postgresql
sql-order-by
sql-in
alat pemecah buah keras
sumber
sumber
Jawaban:
Anda dapat melakukannya dengan mudah dengan (diperkenalkan pada PostgreSQL 8.2) VALUES (), ().
Sintaksnya akan seperti ini:
sumber
with ordered_products as (select row_number() OVER (ORDER BY whatever) as reportingorder, id from comments) ... ORDER BY reportingorder
.Hanya karena sangat sulit untuk menemukan dan harus disebarkan: di mySQL ini bisa dilakukan lebih sederhana , tetapi saya tidak tahu apakah itu bekerja di SQL lain.
sumber
ERROR: cannot pass more than 100 arguments to a function
Dalam Postgres 9.4 atau lebih baru, ini mungkin paling sederhana dan tercepat :
Menggunakan yang baru
WITH ORDINALITY
, yang @a_horse sudah sebutkan .Kami tidak memerlukan subquery, kami dapat menggunakan fungsi set-return seperti tabel.
Sebuah string literal untuk diserahkan dalam array daripada konstruktor ARRAY mungkin lebih mudah untuk diterapkan dengan beberapa klien.
Penjelasan detail:
sumber
Saya pikir cara ini lebih baik:
sumber
... order by id=? desc, id=? desc, id=? desc
dan tampaknya berfungsi dengan baik :-)Dengan Postgres 9.4 ini dapat dilakukan sedikit lebih pendek:
Atau sedikit lebih kompak tanpa tabel turunan:
Menghapus kebutuhan untuk secara manual menetapkan / mempertahankan posisi untuk setiap nilai.
Dengan Postgres 9.6 ini dapat dilakukan dengan menggunakan
array_position()
:CTE digunakan sehingga daftar nilai hanya perlu ditentukan satu kali. Jika itu tidak penting, ini juga dapat ditulis sebagai:
sumber
IN
daftar dariWHERE
klausa lagi diORDER BY
klausa, yang menjadikan ini jawaban terbaik imho ... Sekarang hanya untuk menemukan sesuatu yang serupa untuk MySQL ...order by array_position(array[42,48,43], c.id::int);
yang, dapat menyebabkan bug dalam beberapa kasus.array_position(array[42, 48, 43]::bigint[], c.id::bigint)
, jadi tidak perlu truncatebigint
untukint
.Cara lain untuk melakukannya di Postgres adalah dengan menggunakan
idx
fungsinya.Jangan lupa untuk membuat
idx
fungsi terlebih dahulu, seperti dijelaskan di sini: http://wiki.postgresql.org/wiki/Array_Indexsumber
CREATE EXTENSION intarray;
.enable_extension
akan memungkinkan Anda mengaktifkannya selama pengguna aplikasi Anda adalah anggotards_superuser
grup.Dalam Postgresql:
sumber
position(id::text in '123,345,3,678')
. Id3
akan cocok sebelum id345
, bukan?Pada penelitian ini lagi saya menemukan solusi ini:
Namun ini tampaknya agak bertele-tele dan mungkin memiliki masalah kinerja dengan dataset besar. Adakah yang bisa berkomentar tentang masalah ini?
sumber
IN
klausa? karena saya harus melakukannya untuk ribuan catatan.Untuk melakukan ini, saya pikir Anda mungkin harus memiliki tabel "ORDER" tambahan yang mendefinisikan pemetaan ID untuk dipesan (secara efektif melakukan apa yang dikatakan oleh jawaban Anda atas pertanyaan Anda sendiri), yang kemudian dapat Anda gunakan sebagai kolom tambahan pada pilih yang Anda kemudian dapat memilah.
Dengan cara itu, Anda secara eksplisit menggambarkan pemesanan yang Anda inginkan dalam database, di mana seharusnya.
sumber
sans SEQUENCE, hanya berfungsi pada 8.4:
sumber
atau jika Anda lebih memilih kejahatan daripada kebaikan:
sumber
Dan inilah solusi lain yang berfungsi dan menggunakan tabel konstan ( http://www.postgresql.org/docs/8.3/interactive/sql-values.html ):
Tapi sekali lagi saya tidak yakin ini adalah pemain.
Saya punya banyak jawaban sekarang. Bisakah saya mendapatkan suara dan komentar, jadi saya tahu mana pemenangnya!
Terima kasih semuanya :-)
sumber
[EDIT]
Unest belum terpasang di 8.3, tetapi Anda bisa membuatnya sendiri (keindahan dari * apa pun):
fungsi itu dapat bekerja dalam jenis apa pun:
sumber
Peningkatan sedikit atas versi yang menggunakan urutan saya pikir:
sumber
di sini, [bbs] adalah tabel utama yang memiliki bidang yang disebut id, dan, id adalah array yang menyimpan comments.id.
disahkan pada postgresql 9.6
sumber
Mari kita mendapatkan kesan visual tentang apa yang sudah dikatakan. Misalnya Anda memiliki tabel dengan beberapa tugas:
Dan Anda ingin memesan daftar tugas berdasarkan statusnya. Statusnya adalah daftar nilai string:
Caranya adalah dengan memberikan setiap nilai status interger dan memesan daftar numerik:
Yang mengarah ke:
Credit @ user80168
sumber
Saya setuju dengan semua poster lain yang mengatakan "jangan lakukan itu" atau "SQL tidak bagus dalam hal itu". Jika Anda ingin mengurutkan berdasarkan segi komentar lalu tambahkan kolom integer lain ke salah satu tabel Anda untuk menampung kriteria pengurutan Anda dan urutkan berdasarkan nilai itu. mis. "ORDER BY comments.sort DESC" Jika Anda ingin mengurutkan ini dalam urutan yang berbeda setiap kali ... SQL tidak cocok untuk Anda dalam kasus ini.
sumber