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

Sử dụng một cái gì đó như TOP với GROUP BY

Bạn có thể tìm hành khách có tên dài nhất cho mỗi nhóm một cách thuận tiện với DISTINCT ON .

Nhưng tôi không thấy có cách nào để kết hợp điều đó (hoặc bất kỳ cách đơn giản nào khác) với truy vấn ban đầu của bạn trong một SELECT duy nhất . Tôi khuyên bạn nên tham gia hai truy vấn phụ riêng biệt:

SELECT *
FROM  (  -- your original query
   SELECT orig
        , count(*) AS flight_cnt
        , count(distinct passenger) AS pass_cnt
        , percentile_cont(0.5) WITHIN GROUP (ORDER BY bags) AS bag_cnt_med
   FROM   table1
   GROUP  BY orig
   ) org_query
JOIN  (  -- my addition
   SELECT DISTINCT ON (orig) orig, passenger AS pass_max_len_name
   FROM   table1
   ORDER  BY orig, length(passenger) DESC NULLS LAST
   ) pas USING (orig);

USING trong mệnh đề tham gia thuận tiện chỉ xuất ra một phiên bản của orig , vì vậy bạn có thể chỉ cần sử dụng SELECT * trong SELECT bên ngoài .

Nếu passenger có thể là NULL, điều quan trọng là phải thêm NULLS LAST :

Từ nhiều tên hành khách có cùng độ dài tối đa trong cùng một nhóm, bạn sẽ có lượt chọn tùy ý - trừ khi bạn thêm nhiều biểu thức hơn vào ORDER BY như tiebreaker. Giải thích chi tiết trong câu trả lời được liên kết ở trên.

Hiệu suất?

Thông thường, một lần quét vượt trội hơn, đặc biệt là với các lần quét tuần tự.

Truy vấn trên sử dụng hai quét (có thể quét chỉ mục / chỉ mục). Nhưng lần quét thứ hai tương đối rẻ trừ khi bảng quá lớn để chứa trong bộ nhớ cache (chủ yếu). Lukas đã đề xuất một truy vấn thay thế chỉ với một đơn SELECT thêm:

, (ARRAY_AGG (passenger ORDER BY LENGTH (passenger) DESC))[1]  -- I'd add NULLS LAST

Ý tưởng này thật thông minh, nhưng lần cuối tôi đã thử nghiệm , array_agg với ORDER BY đã không hoạt động quá tốt. (Chi phí của mỗi nhóm ORDER BY là quan trọng và việc xử lý mảng cũng tốn kém.)

Cách tiếp cận tương tự có thể rẻ hơn với hàm tổng hợp tùy chỉnh first() như được hướng dẫn trong Postgres Wiki tại đây . Hoặc nhanh hơn, với phiên bản được viết bằng C, có sẵn trên PGXN . Loại bỏ chi phí bổ sung cho việc xử lý mảng, nhưng chúng tôi vẫn cần ORDER BY cho mỗi nhóm . Có thể nhanh hơn chỉ dành cho một số nhóm. Sau đó, bạn sẽ thêm:

 , first(passenger ORDER BY length(passenger) DESC NULLS LAST)

Gordon Lukas cũng đề cập đến hàm cửa sổ first_value() . Các chức năng của cửa sổ được áp dụng sau Chức năng tổng hợp. Để sử dụng nó trong cùng một SELECT , chúng tôi cần tổng hợp passenger bằng cách nào đó đầu tiên - bắt 22. Gordon giải quyết vấn đề này bằng một truy vấn con - một ứng cử viên khác cho hiệu suất tốt với Postgres tiêu chuẩn.

first() thực hiện tương tự mà không cần truy vấn con và sẽ đơn giản hơn và nhanh hơn một chút. Nhưng nó vẫn sẽ không nhanh hơn một DISTINCT ON riêng biệt đối với hầu hết các trường hợp có ít hàng cho mỗi nhóm. Đối với nhiều hàng trên mỗi nhóm, kỹ thuật CTE đệ quy thường nhanh hơn. Có những kỹ thuật nhanh hơn nếu bạn có một bảng riêng chứa tất cả các orig có liên quan, duy nhất các giá trị. Chi tiết:

Giải pháp tốt nhất phụ thuộc vào các yếu tố khác nhau. miếng bánh pudding đang bị ăn dở. Để tối ưu hóa hiệu suất, bạn phải kiểm tra thiết lập của mình. Truy vấn trên phải là một trong những truy vấn nhanh nhất.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách di chuyển từ SQLite sang PostgreSQL (Rails)

  2. Cách Div () hoạt động trong PostgreSQL

  3. Truy vấn postgres để kiểm tra một chuỗi có phải là một số không

  4. hàm UNIX_TIMESTAMP không tồn tại

  5. Kiến thức cơ bản về kích hoạt PostgreSQL và hàm được lưu trữ