PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Sự khác biệt giữa Postgres DISTINCT và DISTINCT ON là gì?

DISTINCT và DISTINCT ON có ngữ nghĩa hoàn toàn khác nhau.

Đầu tiên là lý thuyết

DISTINCT áp dụng cho toàn bộ bộ giá trị. Sau khi kết quả của truy vấn được tính toán, DISTINCT sẽ xóa mọi bộ giá trị trùng lặp khỏi kết quả.

Ví dụ, giả sử một bảng R với nội dung sau:

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

(6 hàng)

CHỌN khác biệt * với R sẽ cho kết quả:

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

Lưu ý rằng sự khác biệt áp dụng cho toàn bộ danh sách các thuộc tính dự kiến:do đó

select distinct * from R

tương đương về mặt ngữ nghĩa với

select distinct a,b from R

Bạn không thể phát hành

select a, distinct b From R

DISTINCT phải theo sau SELECT. Nó áp dụng cho toàn bộ tuple, không áp dụng cho một thuộc tính của kết quả.

CHẨN ĐOÁN BẬT là một bổ sung postgresql cho ngôn ngữ. Nó tương tự, nhưng không giống nhau, để nhóm theo.

Cú pháp của nó là:

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

Ví dụ:

 SELECT DISTINCT ON (a) * from R

Ngữ nghĩa của nó có thể được mô tả như sau. Tính toán truy vấn như bình thường - không có DISTINCT ON (a) --- nhưng trước khi chiếu kết quả, hãy sắp xếp kết quả hiện tại và nhóm nó theo danh sách thuộc tính trong DISTINCT ON (tương tự như nhóm theo). Bây giờ, hãy thực hiện phép chiếu bằng cách sử dụng bộ đầu tiên trong mỗi nhóm và bỏ qua các bộ khác.

Ví dụ:

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

Sau đó, với mọi giá trị khác nhau của a, lấy bộ giá trị đầu tiên. Tương tự như:

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

Một số DBMS (đáng chú ý nhất là sqlite) sẽ cho phép bạn chạy truy vấn này:

 SELECT a,b from R group by a;

Và điều này cho bạn một kết quả tương tự.

Postgresql sẽ cho phép truy vấn này, nếu và chỉ khi có phụ thuộc hàm từ a đến b. Nói cách khác, truy vấn này sẽ hợp lệ nếu đối với bất kỳ trường hợp nào của quan hệ R, chỉ có một bộ giá trị duy nhất cho mọi giá trị hoặc a (do đó việc chọn bộ giá trị đầu tiên là xác định:chỉ có một bộ giá trị).

Ví dụ:nếu khóa chính của R là a, thì a-> b và:

SELECT a, b FROM R group by a

giống với:

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

Bây giờ, quay lại vấn đề của bạn:

Truy vấn đầu tiên:

SELECT DISTINCT count(dimension1)
FROM data_table;

tính toán số lượng của thứ nguyên1 (số bộ giá trị trong data_table mà ở đó thứ nguyên1 không rỗng). Truy vấn này trả về một bộ, luôn là duy nhất (do đó DISTINCT là dự phòng).

Truy vấn 2:

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

Đây là truy vấn trong một truy vấn. Để tôi viết lại cho rõ ràng:

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

Hãy để chúng tôi tính toán tmp_table đầu tiên. Như tôi đã đề cập ở trên, trước tiên chúng ta hãy bỏ qua DISTINCT ON và thực hiện phần còn lại của truy vấn. Đây là một nhóm theo thứ nguyên1. Do đó, phần này của truy vấn sẽ dẫn đến một bộ giá trị trên mỗi giá trị khác nhau của thứ nguyên1.

Bây giờ, DISTINCT ON. Nó sử dụng lại thứ nguyên1. Nhưng thứ nguyên1 đã là duy nhất (do nhóm của). Do đó, điều này làm cho việc DISTINCT ON superflouos (nó không có tác dụng gì). Tổng số cuối cùng chỉ đơn giản là đếm tất cả các bộ giá trị trong nhóm bằng.

Như bạn có thể thấy, có một sự tương đương trong truy vấn sau (nó áp dụng cho bất kỳ mối quan hệ nào với một thuộc tính a):

SELECT (DISTINCT ON a) a
FROM R

SELECT a FROM R group by a

SELECT DISTINCT a FROM R

Cảnh báo

Sử dụng DISTINCT ON kết quả trong một truy vấn có thể không xác định đối với bất kỳ trường hợp cụ thể nào của cơ sở dữ liệu. Nói cách khác, truy vấn có thể trả về các kết quả khác nhau cho cùng một bảng.

Một khía cạnh thú vị

Distinction ON mô phỏng một xấu hành vi của sqlite theo cách rõ ràng hơn nhiều. Giả sử rằng R có hai thuộc tính a và b:

SELECT a, b FROM R group by a

là một câu lệnh bất hợp pháp trong SQL. Tuy nhiên, nó chạy trên sqlite. Nó chỉ đơn giản là lấy một giá trị ngẫu nhiên của b từ bất kỳ bộ giá trị nào trong nhóm các giá trị giống nhau của a. Trong Postgresql câu lệnh này là bất hợp pháp. Thay vào đó, bạn phải sử dụng DISTINCT ON và viết:

SELECT DISTINCT ON (a) a,b from R

Hệ quả

DISTINCT ON hữu ích trong một nhóm khi bạn muốn truy cập một giá trị phụ thuộc về mặt chức năng vào nhóm theo thuộc tính. Nói cách khác, nếu bạn biết rằng đối với mọi nhóm thuộc tính, chúng luôn có cùng một giá trị của thuộc tính thứ ba, thì hãy sử dụng DISTINCT TRÊN nhóm thuộc tính đó. Nếu không, bạn sẽ phải tạo một JOIN để truy xuất thuộc tính thứ ba đó.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Không thể cài đặt plpython cho postgres 12

  2. Đọc tệp CSV / Excel từ tệp SFTP, thực hiện một số thay đổi trong các tệp đó bằng Pandas và lưu lại

  3. Nhận khóa chính không xác định cho bảng trong khi ID ở đó

  4. Triển khai thiết lập đa trung tâm dữ liệu cho PostgreSQL - Phần một

  5. Chèn nhiều bản ghi với pg-promise