Định nghĩa của bạn:
hoạt động từ nhóm B luôn diễn ra sau hoạt động từ nhóm A.
.. ngụ ý một cách hợp lý rằng có 0 hoặc 1 hoạt động B sau 1 hoặc nhiều hoạt động A trên mỗi người dùng. Không bao giờ có nhiều hơn 1 B hoạt động theo trình tự.
Bạn có thể làm cho nó hoạt động với một chức năng cửa sổ duy nhất, DISTINCT ON
và CASE
, đó sẽ là cách nhanh nhất cho một số ít hàng cho mỗi người dùng (cũng xem bên dưới):
SELECT name
, CASE WHEN a2 LIKE 'B%' THEN a1 ELSE a2 END AS activity
, CASE WHEN a2 LIKE 'B%' THEN a2 END AS next_activity
FROM (
SELECT DISTINCT ON (name)
name
, lead(activity) OVER (PARTITION BY name ORDER BY time DESC) AS a1
, activity AS a2
FROM t
WHERE (activity LIKE 'A%' OR activity LIKE 'B%')
ORDER BY name, time DESC
) sub;
db <> fiddle here
Một CASE
trong SQL biểu thức mặc định thành NULL
nếu không có ELSE
nhánh đã được thêm vào, vì vậy tôi đã giữ nguyên nhánh đó.
Giả sử time
được định nghĩa NOT NULL
. Ngoài ra, bạn có thể muốn thêm NULLS LAST
. Tại sao?
- Sắp xếp theo ASC cột, nhưng giá trị NULL trước?
(activity LIKE 'A%' OR activity LIKE 'B%')
dài dòng hơn activity ~ '^[AB]'
, nhưng thường nhanh hơn trong các phiên bản Postgres cũ hơn. Giới thiệu về đối sánh mẫu:
- Đối sánh mẫu với LIKE, SIMILAR TO hoặc biểu thức chính quy trong PostgreSQL
Các chức năng của cửa sổ có điều kiện?
Điều đó thực sự có thể . Bạn có thể kết hợp FILTER
tổng hợp mệnh đề với OVER
mệnh đề của các chức năng cửa sổ. Tuy nhiên :
-
FILTER
bản thân mệnh đề chỉ có thể hoạt động với các giá trị từ hàng hiện tại. -
Quan trọng hơn,
FILTER
không được triển khai cho các hàm chính hãng thuần túy nhưlead()
hoặclag()
(lên đến Postgres 13) - chỉ dành cho các chức năng tổng hợp.
Nếu bạn thử:
lead(activity) FILTER (WHERE activity LIKE 'A%') OVER () AS activity
Postgres sẽ cho bạn biết:
FILTER is not implemented for non-aggregate window functions
Giới thiệu về FILTER
:
- Tổng hợp các cột với các bộ lọc bổ sung (riêng biệt)
- Tham chiếu hàng hiện tại trong mệnh đề FILTER của hàm cửa sổ
Hiệu suất
Đối với vài người dùng có ít hàng cho mỗi người dùng, khá nhiều bất kỳ truy vấn nhanh, ngay cả khi không có chỉ mục.
Đối với nhiều người dùng và số ít hàng cho mỗi người dùng, truy vấn đầu tiên ở trên phải nhanh nhất. Xem:
- Chọn hàng đầu tiên trong mỗi GROUP BY nhóm?
Đối với nhiều hàng cho mỗi người dùng, có (có thể có nhiều ) kỹ thuật nhanh hơn, tùy thuộc vào chi tiết thiết lập của bạn. Xem:
- Tối ưu hóa truy vấn GROUP BY để truy xuất hàng mới nhất cho mỗi người dùng