Saya ingin menjalankan kueri ini:
SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
FROM purchases
WHERE purchases.product_id = 1
ORDER BY purchases.purchased_at DESC
Tapi saya mendapatkan kesalahan ini:
PG :: Kesalahan: ERROR: SELECT DISTINCT ON ekspresi harus cocok dengan ekspresi ORDER BY awal
Menambahkan address_id
sebagai ORDER BY
ekspresi pertama membungkam kesalahan, tetapi saya benar-benar tidak ingin menambahkan penyortiran address_id
. Apakah mungkin dilakukan tanpa memesan address_id
?
sql
postgresql
sql-order-by
distinct-on
sl_bug
sumber
sumber
Jawaban:
Dokumentasi mengatakan:
Dokumentasi resmi
Jadi, Anda harus menambahkan
address_id
ke pesanan dengan.Atau, jika Anda mencari baris penuh yang berisi produk yang paling baru dibeli untuk masing-masing
address_id
dan hasil yang diurutkanpurchased_at
kemudian Anda mencoba untuk memecahkan masalah N per kelompok terbesar yang dapat diselesaikan dengan pendekatan berikut:Solusi umum yang harus bekerja di sebagian besar DBMS:
Solusi berorientasi PostgreSQL yang lebih berdasarkan pada jawaban @ hkf:
Masalah diklarifikasi, diperluas dan diselesaikan di sini: Memilih baris yang dipesan oleh beberapa kolom dan berbeda pada yang lain
sumber
SELECT DISTINCT ON (purchases.purchased_at, address_id)
. Namun, dua catatan dengan address_id yang sama tetapi nilai buying_at yang berbeda akan menghasilkan duplikat di set yang dikembalikan. Pastikan Anda mengetahui data yang Anda tanyakan.Anda dapat memesan dengan address_id dalam subquery, lalu memesan dengan apa yang Anda inginkan dalam kueri luar.
sumber
select
, saya rasa ini bukan kode produksi?address_id
dua kali (tanpa perlu). Banyak klien memiliki masalah dengan nama kolom duplikat.ORDER BY address_id DESC
tidak ada gunanya dan menyesatkan. Itu tidak berguna dalam permintaan ini. Hasilnya adalah pemilihan acak dari setiap rangkaian baris dengan yang samaaddress_id
, bukan baris dengan yang terbarupurchased_at
. Pertanyaan ambigu tidak menanyakan hal itu secara eksplisit, tetapi itu hampir pasti maksud OP. Singkatnya: jangan gunakan kueri ini . Saya memposting alternatif dengan penjelasan.Sebuah subquery bisa mengatasinya:
Ekspresi terkemuka di
ORDER BY
harus setuju dengan kolom diDISTINCT ON
, sehingga Anda tidak dapat memesan dengan kolom yang berbeda di kolom yang samaSELECT
.Hanya gunakan tambahan
ORDER BY
di subquery jika Anda ingin memilih baris tertentu dari setiap set:Jika
purchased_at
bisaNULL
, pertimbangkanDESC NULLS LAST
. Tetapi pastikan untuk mencocokkan indeks Anda jika Anda ingin menggunakannya. Lihat:Terkait, dengan penjelasan lebih lanjut:
sumber
DISTINCT ON
tanpa pencocokanORDER BY
. Permintaan pertama membutuhkan bagianORDER BY address_id
dalam subquery.DISTINCT ON
tanpaORDER BY
di kueri yang sama. Anda mendapatkan baris sewenang-wenang dari setiap set rekan yang ditentukan olehDISTINCT ON
klausa dalam kasus ini. Cobalah atau ikuti tautan di atas untuk detail dan tautan ke manual.ORDER BY
dalam permintaan yang sama (samaSELECT
) tidak bisa tidak setuju denganDISTINCT ON
. Saya memang menjelaskan itu juga.ORDER BY
digunakan" dalam dokumen karena tidak masuk akal bagi saya bahwa fitur tersebut diterapkan untuk dapat menangani set nilai yang tidak berurutan ... namun tidak akan memungkinkan Anda untuk mengeksploitasinya dengan pemesanan eksplisit. Mengganggu.DISTINCT ON
ekspresi (belum).Fungsi jendela dapat menyelesaikannya dalam satu pass:
sumber
address_id
. Prinsipnya bisa bekerja. Contoh terkait: stackoverflow.com/a/22064571/939860 atau stackoverflow.com/a/11533808/939860 . Tetapi ada pertanyaan yang lebih pendek dan / atau lebih cepat untuk masalah yang dihadapi.Bagi siapa pun yang menggunakan Flask-SQLAlchemy, ini bekerja untuk saya
sumber
query.distinct(foo).from_self().order(bar)
Purchases.query
?Anda juga dapat melakukan ini dengan menggunakan grup dengan klausa
sumber
purchases
hanya memiliki dua kolomaddress_id
danpurchased_at
). Karena ituGROUP BY
, Anda harus menggunakan fungsi agregat untuk mendapatkan nilai dari setiap kolom yang tidak digunakan untuk pengelompokan, sehingga nilai-nilai mereka semua akan berasal dari baris yang berbeda dari grup kecuali Anda pergi melalui senam yang jelek dan tidak efisien. Ini dapat diperbaiki hanya dengan menggunakan fungsi jendela daripadaGROUP BY
.