PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Apa perbedaan antara Postgres DISTINCT vs DISTINCT ON?

DISTINCT dan DISTINCT ON memiliki semantik yang sama sekali berbeda.

Pertama teorinya

DISTINCT berlaku untuk seluruh tuple. Setelah hasil kueri dihitung, DISTINCT menghapus tupel duplikat dari hasil.

Misalnya, asumsikan tabel R dengan konten berikut:

#table r;
a | b 
---+---
1 | a
2 | b
3 | c
3 | d
2 | e
1 | a

(6 baris)

SELECT berbeda * dari R akan menghasilkan:

# select distinct * from r;
 a | b 
---+---
 1 | a
 3 | d
 2 | e
 2 | b
 3 | c
(5 rows)

Perhatikan bahwa perbedaan berlaku untuk seluruh daftar atribut yang diproyeksikan:demikian

select distinct * from R

secara semantik setara dengan

select distinct a,b from R

Anda tidak dapat mengeluarkan

select a, distinct b From R

DISTINCT harus mengikuti SELECT. Ini berlaku untuk seluruh tuple, bukan untuk atribut hasil.

BEDA AKTIF adalah tambahan postgresql untuk bahasa. Ini mirip, tetapi tidak identik, untuk dikelompokkan berdasarkan.

Sintaksnya adalah:

 SELECT DISTINCT ON (attributeList) <rest as any query>

Misalnya:

 SELECT DISTINCT ON (a) * from R

Semantiknya dapat digambarkan sebagai berikut. Hitung kueri seperti biasa--tanpa DISTINCT ON (a)----tetapi sebelum proyeksi hasil, urutkan hasil saat ini dan kelompokkan menurut daftar atribut di DISTINCT ON (mirip dengan group by). Sekarang, lakukan proyeksi menggunakan tupel pertama di setiap grup dan abaikan tupel lainnya.

Contoh:

select distinct * from r order by a;
     a | b 
    ---+---
     1 | a
     2 | e
     2 | b
     3 | c
     3 | d
    (5 rows)

Kemudian untuk setiap nilai a yang berbeda, ambil tupel pertama. Yang sama dengan:

 SELECT DISTINCT on (a) * from r;
  a | b 
 ---+---
 1 | a
 2 | b
 3 | c
 (3 rows)

Beberapa DBMS (terutama sqlite) memungkinkan Anda menjalankan kueri ini:

 SELECT a,b from R group by a;

Dan ini memberi Anda hasil yang serupa.

Postgresql akan mengizinkan kueri ini, jika dan hanya jika ada ketergantungan fungsional dari a ke b. Dengan kata lain, kueri ini akan valid jika untuk setiap instance dari relasi R, hanya ada satu tupel unik untuk setiap nilai atau a (sehingga memilih tupel pertama bersifat deterministik:hanya ada satu tupel).

Misalnya, jika kunci utama dari R adalah a, maka a->b dan:

SELECT a,b FROM R group by a

identik dengan:

  SELECT DISTINCT on (a) a, b from r;

Sekarang, kembali ke masalah Anda:

Permintaan pertama:

SELECT DISTINCT count(dimension1)
FROM data_table;

menghitung jumlah dimensi1 (jumlah tupel dalam tabel_data yang di mana dimensi1 tidak nol). Kueri ini mengembalikan satu tupel, yang selalu unik (karenanya DISTINTI redundan).

Pertanyaan 2:

SELECT count(*)
FROM (SELECT DISTINCT ON (dimension1) dimension1
FROM data_table
GROUP BY dimension1) AS tmp_table;

Ini adalah kueri dalam kueri. Biarkan saya menulis ulang untuk kejelasan:

WITH tmp_table AS (
   SELECT DISTINCT ON (dimension1) 
     dimension1 FROM data_table
     GROUP by dimension1) 
SELECT count(*) from tmp_table

Mari kita hitung dulu tmp_table. Seperti yang saya sebutkan di atas, pertama-tama mari kita abaikan DISTINCT ON dan lakukan sisa permintaan. Ini adalah grup menurut dimensi1. Karenanya bagian kueri ini akan menghasilkan satu tupel per nilai dimensi1 yang berbeda.

Sekarang, BERBEDA ON. Ini menggunakan dimensi1 lagi. Tetapi dimensi1 sudah unik (karena pengelompokannya oleh). Oleh karena itu, ini membuat DISTINCT ON superflouos (tidak melakukan apa-apa). Hitungan terakhir hanyalah hitungan semua tupel dalam grup dengan.

Seperti yang Anda lihat, ada kesetaraan dalam kueri berikut (ini berlaku untuk semua relasi dengan atribut a):

SELECT (DISTINCT ON a) a
FROM R

dan

SELECT a FROM R group by a

dan

SELECT DISTINCT a FROM R

Peringatan

Menggunakan DISTINCT ON hasil dalam kueri mungkin non-deterministik untuk setiap instance database yang diberikan. Dengan kata lain, kueri mungkin mengembalikan hasil yang berbeda untuk tabel yang sama.

Satu aspek yang menarik

Distinct ON mengemulasi buruk perilaku sqlite dengan cara yang jauh lebih bersih. Asumsikan bahwa R memiliki dua atribut a dan b:

SELECT a, b FROM R group by a

adalah pernyataan ilegal dalam SQL. Namun, itu berjalan di sqlite. Ini hanya mengambil nilai acak b dari tupel mana pun dalam grup nilai yang sama dari a. Dalam Postgresql, pernyataan ini ilegal. Sebagai gantinya, Anda harus menggunakan DISTINCT ON dan menulis:

SELECT DISTINCT ON (a) a,b from R

Akibat wajar

DISTINCT ON berguna dalam grup saat Anda ingin mengakses nilai yang secara fungsional bergantung pada grup berdasarkan atribut. Dengan kata lain, jika Anda tahu bahwa untuk setiap kelompok atribut mereka selalu memiliki nilai yang sama dari atribut ketiga, maka gunakan DISTINCT ON kelompok atribut tersebut. Jika tidak, Anda harus membuat JOIN untuk mengambil atribut ketiga tersebut.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. dereferensi array 2d postgres

  2. Peringatan Postgres pl/java

  3. Gambaran Umum Prosedur Tersimpan Baru di PostgreSQL 11

  4. Tabel Postgres ke array dua dimensi

  5. konversi tanggal ke integer di postgresql