Trong SQL, theo như tôi biết, thứ tự xử lý truy vấn logic, là thứ tự diễn giải khái niệm, bắt đầu bằng TỪ theo cách sau:
- TỪ
- Ở ĐÂU
- NHÓM THEO
- ĐANG CÓ
- LỰA CHỌN
- ĐẶT BỞI
Theo dõi danh sách này, thật dễ dàng để biết lý do tại sao bạn không thể có bí danh CHỌN trong mệnh đề WHERE, vì bí danh chưa được tạo. T-SQL (SQL Server) tuân thủ nghiêm ngặt điều này và bạn không thể sử dụng bí danh CHỌN cho đến khi bạn vượt qua CHỌN.
Nhưng trong MySQL, có thể sử dụng các bí danh SELECT trong mệnh đề HAVING ngay cả khi nó phải (về mặt logic) được xử lý trước mệnh đề SELECT. Làm thế nào điều này có thể có thể?
Để đưa ra một ví dụ:
SELECT YEAR(orderdate), COUNT(*) as Amount
FROM Sales.Orders
GROUP BY YEAR(orderdate)
HAVING Amount>1;
Câu lệnh không hợp lệ trong T-SQL (vì HAVING đang đề cập đến bí danh SELECT Amount
) ...
Msg 207, Level 16, State 1, Line 5
Invalid column name 'Amount'.
... nhưng hoạt động tốt trong MySQL.
Dựa trên điều này, tôi tự hỏi:
- Có phải MySQL đang dùng một phím tắt trong các quy tắc SQL để giúp người dùng? Có thể sử dụng một số loại phân tích trước?
- Hoặc là MySQL sử dụng một thứ tự giải thích khái niệm khác với thứ tự tôi mặc dù tất cả RDBMS đang theo dõi?
SELECT C, ROW_NUMBER() OVER (ORDER BY X) AS RN FROM T GROUP BY C HAVING RN = 1
sẽ có vấn đề như ROW_NUMBER
chạy sau sựHAVING
SELECT @rownum:=@rownum + 1 as row ...
. Có lẽ lý do tại sao họ hỗ trợ bí danh CHỌN đơn giản là vì họ có thể, do thực tế là họ không hỗ trợ những thứ sẽ khiến điều đó không thể ... ai biết? :)
HAVING
và SELECT
mệnh đề có thể được hoán đổi cho nhau. Vì vậy, không có sự mơ hồ trong việc này và có thể đơn giản hóa giao diện của mã khi có các biểu thức quái dị trong SELECT
.