Đối với bảng hiện tại của 1,700
hàng, giải pháp của bạn là OK.
Nếu bạn sẽ có số 100,000
hàng, DISTINCT
có thể trở nên không hiệu quả.
Dưới đây là bài viết trong blog của tôi cho thấy làm thế nào để làm điều đó một cách hiệu quả:
Giải pháp này sử dụng một chỉ mục trên name
. Nó sẽ nhảy qua các phím chỉ mục, chọn từng chữ cái đầu tiên nhiều nhất một lần.
Trước tiên, bạn sẽ cần phải tạo một hàm:
CREATE FUNCTION fn_get_next_code(initial INT) RETURNS INT
NOT DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE _next VARCHAR(200);
DECLARE EXIT HANDLER FOR NOT FOUND RETURN NULL;
SELECT ORD(SUBSTRING(name, 1, 1))
INTO _next
FROM t_names
WHERE name >= CHAR(initial + 1)
ORDER BY
name
LIMIT 1;
RETURN _next;
END
Chức năng này, được đưa ra một bộ quy tắc thư bắt đầu, trả về thư xuất phát đầu tiên bên cạnh đưa từ bảng.
Thứ hai, sử dụng chức năng này trong một truy vấn:
SELECT CHAR(@r) AS starting,
@r := fn_get_next_letter(@r) AS next
FROM (
SELECT @r := ORD(LEFT(MIN(name), 1))
) vars, mytable
WHERE @r IS NOT NULL
Trên mỗi lần lặp, phiên biến @r
sẽ bỏ qua để lá thư bắt đầu tiếp theo sử dụng một chỉ mục.
Điều này sẽ rất nhanh, nhưng nó chỉ trả tiền nếu bạn có hàng trăm nghìn hàng.
Nếu không, chỉ sử dụng DISTINCT
.
Bạn có bao nhiêu bản ghi trong bảng?Tôi muốn đăng một phiên bản được tối ưu hóa nhưng không biết liệu có bận tâm không :) – Quassnoi
OK, tôi đã đăng nó :) Có lẽ ngày mai tôi sẽ đăng một bài đăng trong blog của tôi ra khỏi câu hỏi của bạn. – Quassnoi