Bagaimana saya (atau saya) PILIH BERBEDA pada beberapa kolom?

Saya perlu untuk mengambil semua baris dari tabel yang mana 2 kolom gabungan semua berbeda. Jadi saya ingin semua penjualan yang tidak memiliki penjualan yang terjadi pada hari yang sama untuk harga yang sama. Penjualan yang unik berdasarkan hari dan harga yang akan mendapatkan update ke status aktif.

Jadi saya'm berpikir:

UPDATE sales
SET status = 'ACTIVE'
WHERE id IN (SELECT DISTINCT (saleprice, saledate), id, count(id)
             FROM sales
             HAVING count = 1)

Tapi otak saya sakit akan lebih jauh dari itu.

Larutan
SELECT DISTINCT a,b,c FROM t

adalah roughly setara dengan:

SELECT a,b,c FROM t GROUP BY a,b,c

It's merupakan ide yang baik untuk mendapatkan digunakan untuk KELOMPOK DENGAN sintaks, seperti's lebih kuat.

Untuk pertanyaan anda, saya'd lakukan seperti ini:

UPDATE sales
SET status='ACTIVE'
WHERE id IN
(
    SELECT id
    FROM sales S
    INNER JOIN
    (
        SELECT saleprice, saledate
        FROM sales
        GROUP BY saleprice, saledate
        HAVING COUNT(*) = 1 
    ) T
    ON S.saleprice=T.saleprice AND s.saledate=T.saledate
 )
Komentar (3)

Jika anda menempatkan bersama-sama jawaban sejauh ini, membersihkan dan memperbaiki, anda akan tiba di segala query:

UPDATE sales
SET    status = 'ACTIVE'
WHERE  (saleprice, saledate) IN (
    SELECT saleprice, saledate
    FROM   sales
    GROUP  BY saleprice, saledate
    HAVING count(*) = 1 
    );

Yang banyak lebih cepat daripada salah satu dari mereka. Nuklir kinerja saat ini jawaban yang diterima oleh faktor 10 - 15 (dalam tes saya pada PostgreSQL 8.4 dan 9.1).

Tapi ini masih jauh dari optimal. Gunakan TIDAK ADA (anti-)semi-bergabung untuk kinerja yang lebih baik. ADA adalah standar SQL, telah sekitar selamanya (setidaknya sejak PostgreSQL 7.2, jauh sebelum pertanyaan ini diminta) dan cocok disajikan persyaratan sempurna:

UPDATE sales s
SET    status = 'ACTIVE'
WHERE  NOT EXISTS (
   SELECT FROM sales s1                     -- SELECT list can be empty for EXISTS
   WHERE  s.saleprice = s1.saleprice
   AND    s.saledate  = s1.saledate
   AND    s.id  s1.id                     -- except for row itself
   )
AND    s.status IS DISTINCT FROM 'ACTIVE';  -- avoid empty updates. see below

db<>biola di sini Old SQL Biola

Kunci unik mengidentifikasi baris

Jika anda don't memiliki primary atau unique key untuk tabel (id dalam contoh), anda dapat mengganti dengan sistem kolom ctid untuk tujuan ini query (tetapi tidak untuk beberapa tujuan lain):

   AND    s1.ctid  s.ctid

Setiap tabel harus memiliki primary key. Tambahkan satu jika anda tidak't memiliki satu, belum. Saya sarankan serial atau IDENTITAS kolom di Postgres 10+.

Terkait:

Cara ini lebih cepat?

Subquery dalam ADA anti-semi-bergabung dapat berhenti mengevaluasi sesegera pertama dupe ditemukan (tidak ada gunanya melihat lebih jauh). Untuk sebuah meja dengan beberapa duplikat ini hanya sedikit lebih efisien. Dengan banyak duplikat ini menjadi cara lebih efisien.

Mengecualikan kosong update

Untuk baris yang sudah memiliki status = &#39;AKTIF&#39; update ini tidak akan mengubah apa pun, tapi masih menyisipkan baris baru versi penuh biaya (minor pengecualian berlaku). Biasanya, anda tidak ingin ini. Tambahkan lagi di MANA kondisi seperti yang ditunjukkan di atas untuk menghindari hal ini dan membuatnya bahkan lebih cepat:

Jika status didefinisikan NOT NULL, anda dapat menyederhanakan untuk:

AND status  'ACTIVE';

Perbedaan yang halus dalam NULL penanganan

Query ini (tidak seperti saat ini jawaban yang diterima oleh Joel) tidak memperlakukan nilai-nilai NULL sama. Dua baris berikut untuk (saleprice, saledate) akan memenuhi syarat sebagai "yang berbeda" (meskipun tampak identik dengan mata manusia):

(123, NULL)
(123, NULL)

Juga lewat di indeks unik dan hampir di mana pun, karena nilai-nilai NULL tidak membandingkan sama sesuai dengan standar SQL. Lihat:

OTOH, GROUP BY, BERBEDA atau BERBEDA PADA () mengobati NULL nilai-nilai yang sama. Menggunakan query yang sesuai gaya tergantung pada apa yang ingin anda capai. Anda masih dapat menggunakan ini lebih cepat query dengan INI TIDAK BERBEDA DARI bukan = untuk setiap atau semua perbandingan untuk membuat NULL membandingkan sama. Lebih lanjut:

Jika semua kolom yang dibandingkan didefinisikan NOT NULL, tidak ada ruang untuk perbedaan pendapat.

Komentar (12)

Masalah dengan query anda adalah bahwa ketika menggunakan GROUP BY clause (yang pada dasarnya dilakukan dengan menggunakan distinct) anda hanya dapat menggunakan kolom yang anda grup atau fungsi agregat. Anda tidak dapat menggunakan kolom id karena ada potensi nilai-nilai yang berbeda. Dalam kasus anda hanya selalu ada satu nilai karena MEMILIKI klausa, tetapi sebagian besar RDBMS tidak cukup pintar untuk menyadari bahwa.

Ini harus bekerja namun (dan doesn't perlu bergabung):

UPDATE sales
SET status='ACTIVE'
WHERE id IN (
  SELECT MIN(id) FROM sales
  GROUP BY saleprice, saledate
  HAVING COUNT(id) = 1
)

Anda juga bisa menggunakan MAX atau AVG bukan MIN, itu hanya penting untuk menggunakan sebuah fungsi yang mengembalikan nilai dari kolom jika hanya ada satu baris pencocokan.

Komentar (0)

Saya ingin memilih nilai-nilai yang berbeda dari satu kolom 'GrondOfLucht' tapi mereka harus diurutkan dalam urutan seperti yang diberikan dalam kolom 'sortering'. Saya tidak bisa mendapatkan nilai yang berbeda hanya menggunakan satu kolom

Select distinct GrondOfLucht,sortering
from CorWijzeVanAanleg
order by sortering

Hal ini juga akan memberikan kolom 'sortering' dan karena 'GrondOfLucht' DAN 'sortering' adalah tidak unik, hasilnya akan SEMUA baris.

gunakan GRUP untuk memilih catatan 'GrondOfLucht' dalam urutan yang diberikan oleh 'sortering

SELECT        GrondOfLucht
FROM            dbo.CorWijzeVanAanleg
GROUP BY GrondOfLucht, sortering
ORDER BY MIN(sortering)
Komentar (1)

Jika anda DBMS doesn't dukungan berbeda dengan beberapa kolom seperti ini:

select distinct(col1, col2) from table

Multi-pilih secara umum dapat dilaksanakan dengan aman sebagai berikut:

select distinct * from (select col1, col2 from table ) as x

Karena hal ini dapat bekerja pada sebagian besar DBMS dan ini diharapkan akan lebih cepat daripada kelompok dengan solusi seperti yang anda menghindari pengelompokan fungsi.

Komentar (0)