Các chức năng cửa sổ vắng mặt, bạn có thể đặt hàng tbl
và sử dụng các biến người dùng để tự tính toán xếp hạng trên các phân vùng của bạn (giá trị "ngày"):
SELECT "date", -- D) Desired columns
id,
value,
rank
FROM (SELECT "date", -- C) Rank by date
id,
value,
CASE COALESCE(@partition, "date")
WHEN "date" THEN @rank := @rank + 1
ELSE @rank := 1
END AS rank,
@partition := "date" AS dummy
FROM (SELECT @rank := 0 AS rank, -- A) User var init
@partition := NULL AS partition) dummy
STRAIGHT_JOIN
( SELECT "date", -- B) Ordering query
id,
value
FROM tbl
ORDER BY date, value) tbl_ordered;
Cập nhật
Vậy, truy vấn đó đang làm gì?
Chúng tôi đang sử dụng biến người dùng để "lặp" qua tập kết quả được sắp xếp, tăng dần hoặc đặt lại bộ đếm (@rank
) tùy thuộc vào phân đoạn tiếp giáp nào của tập kết quả (được theo dõi trong @partition
) chúng tôi đang tham gia.
Trong truy vấn A chúng tôi khởi tạo hai biến người dùng. Trong truy vấn B chúng tôi nhận được các bản ghi của bảng của bạn theo thứ tự chúng tôi cần:đầu tiên theo ngày và sau đó theo giá trị. Đ và B cùng nhau tạo một bảng dẫn xuất, tbl_ordered
, trông giống như thế này:
rank | partition | "date" | id | value
---- + --------- + ------ + ---- + -----
0 | NULL | d1 | id2 | 1
0 | NULL | d1 | id1 | 2
0 | NULL | d2 | id1 | 10
0 | NULL | d2 | id2 | 11
Hãy nhớ rằng, chúng tôi không thực sự quan tâm đến các cột dummy.rank
và dummy.partition
- chúng chỉ là sự cố về cách chúng tôi khởi tạo các biến @rank
và @partition
.
Trong truy vấn C chúng tôi lặp qua các bản ghi của bảng dẫn xuất. Những gì chúng tôi đang làm ít nhiều giống với những gì mã giả sau đây thực hiện:
rank = 0
partition = nil
foreach row in fetch_rows(sorted_query):
(date, id, value) = row
if partition is nil or partition == date:
rank += 1
else:
rank = 1
partition = date
stdout.write(date, id, value, rank, partition)
Cuối cùng, truy vấn D chiếu tất cả các cột từ C ngoại trừ cho cột giữ @partition
(mà chúng tôi đặt tên là dummy
và không cần hiển thị).