Hầu hết các cơ sở dữ liệu khá rõ ràng về thực tế rằng ORDER BY
một truy vấn con là:
- Không được phép: Ví dụ: SQL Server, Sybase SQL ở mọi nơi (trừ khi được bổ sung
TOP
hoặc OFFSET .. FETCH
)
- Vô nghĩa: Ví dụ PostgreSQL, DB2 (một lần nữa, trừ khi được bổ sung
OFFSET .. FETCH
hoặc LIMIT
)
Đây là một ví dụ từ hướng dẫn LUW của DB2 (nhấn mạnh của tôi)
Mệnh đề ORDER BY trong phần phụ không ảnh hưởng đến thứ tự của các hàng được trả về bởi một truy vấn. Mệnh đề ORDER BY chỉ ảnh hưởng đến thứ tự của các hàng được trả về nếu nó được chỉ định trong fullselect ngoài cùng.
Từ ngữ khá rõ ràng, giống như của PostgreSQL :
Nếu sắp xếp không được chọn, các hàng sẽ được trả về theo thứ tự không xác định. Thứ tự thực tế trong trường hợp đó sẽ phụ thuộc vào các loại kế hoạch quét và tham gia và thứ tự trên đĩa, nhưng không được dựa vào . Một thứ tự đầu ra cụ thể chỉ có thể được đảm bảo nếu bước sắp xếp được chọn rõ ràng.
Từ đặc điểm kỹ thuật này, có thể theo dõi rằng bất kỳ thứ tự nào phát sinh từ ORDER BY
mệnh đề trong bảng dẫn xuất chỉ là ngẫu nhiên và có thể trùng khớp với thứ tự dự kiến của bạn (điều này có trong hầu hết các cơ sở dữ liệu trong ví dụ tầm thường của bạn), nhưng sẽ không khôn ngoan khi dựa vào điều này.
Lưu ý bên lề về DB2:
Cụ thể, DB2 có một tính năng ít được biết đến hơnORDER BY ORDER OF <table-designator>
, có thể được sử dụng như sau:
SELECT C1 FROM
(SELECT C1 FROM T1
UNION
SELECT C1 FROM T2
ORDER BY C1 ) AS UTABLE
ORDER BY ORDER OF UTABLE
Trong trường hợp cụ thể này, thứ tự của bảng dẫn xuất có thể được sử dụng lại một cách rõ ràng trong hầu hết CHỌN bên ngoài
Lưu ý bên lề về Oracle:
Trong nhiều năm, Oracle đã thực hiện OFFSET
phân trang bằng cách sử dụng phân trang ROWNUM
, có thể được tính toán hợp lý chỉ sau khi đặt một bảng dẫn xuất:
SELECT *
FROM (
SELECT rownum AS rn, t.* -- ROWNUM here depends on the derived table's ordering
FROM (
SELECT * FROM table ORDER BY time DESC
) t
) t
WHERE rn BETWEEN 10 AND 20
Có thể dự đoán một cách hợp lý rằng ít nhất là trong sự hiện diện của ROWNUM
một truy vấn, các phiên bản Oracle trong tương lai sẽ không phá vỡ hành vi này để không phá vỡ tất cả các di sản Oracle SQL ngoài kia, vốn chưa được chuyển sang mong muốn hơn nhiều và OFFSET .. FETCH
Cú pháp chuẩn SQL có thể đọc được :
SELECT * FROM table ORDER BY time DESC OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY