Để nhận được kết quả không có truy vấn con , bạn phải dùng đến thủ thuật chức năng cửa sổ nâng cao:
SELECT sum(count(*)) OVER () AS tickets_count
, sum(min(a.revenue)) OVER () AS atendees_revenue
FROM tickets t
JOIN attendees a ON a.id = t.attendee_id
GROUP BY t.attendee_id
LIMIT 1;
sqlfiddle
Nó hoạt động như thế nào?
Chìa khóa để hiểu điều này là chuỗi sự kiện trong truy vấn:
chức năng tổng hợp -> chức năng cửa sổ -> DISTINCT -> LIMIT
Thêm chi tiết:
- Cách tốt nhất để tính kết quả trước khi LIMIT được áp dụng
Từng bước:
-
I
GROUP BY t.attendee_id
- điều mà bạn thường làm trong một truy vấn con. -
Sau đó, tôi tổng hợp các số đếm để có được tổng số vé. Không hiệu quả lắm, nhưng bị ép buộc bởi yêu cầu của bạn. Hàm tổng hợp
count(*)
được bao bọc trong hàm cửa sổsum( ... ) OVER ()
để đến biểu thức không phổ biến:sum(count(*)) OVER ()
.Và tính tổng doanh thu tối thiểu cho mỗi người tham dự để nhận được tổng không trùng lặp.
Bạn cũng có thể sử dụng
max()
hoặcavg()
thay vìmin()
có cùng tác dụng vớirevenue
được đảm bảo là giống nhau cho mọi hàng cho mỗi người tham dự.Điều này có thể đơn giản hơn nếu
DISTINCT
đã được cho phép trong các hàm cửa sổ, nhưng PostgreSQL chưa (chưa) triển khai tính năng này. Theo tài liệu:Các hàm cửa sổ tổng hợp, không giống như các hàm tổng hợp bình thường, không cho phép
DISTINCT
hoặcORDER BY
được sử dụng trong danh sách đối số hàm. -
Bước cuối cùng là lấy một hàng duy nhất. Điều này có thể được thực hiện với
DISTINCT
(Chuẩn SQL) vì tất cả các hàng đều giống nhau.LIMIT 1
sẽ nhanh hơn, mặc dù. Hoặc biểu mẫu chuẩn SQLFETCH FIRST 1 ROWS ONLY
.