Đề xuất đầu tiên của Pradeep Adiga ORDER BY NEWID()
, là tốt và một cái gì đó tôi đã sử dụng trong quá khứ vì lý do này.
Hãy cẩn thận với việc sử dụng RAND()
- trong nhiều ngữ cảnh, nó chỉ được thực hiện một lần cho mỗi câu lệnh vì vậy ORDER BY RAND()
sẽ không có hiệu lực (vì bạn đang nhận được kết quả tương tự từ RAND () cho mỗi hàng).
Ví dụ:
SELECT display_name, RAND() FROM tr_person
trả về mỗi tên từ bảng người của chúng tôi và một số "ngẫu nhiên", giống nhau cho mỗi hàng. Số lượng thay đổi mỗi lần bạn chạy truy vấn, nhưng giống nhau cho mỗi hàng mỗi lần.
Để chỉ ra rằng trường hợp tương tự được RAND()
sử dụng trong ORDER BY
mệnh đề, tôi thử:
SELECT display_name FROM tr_person ORDER BY RAND(), display_name
Các kết quả vẫn được sắp xếp theo tên cho biết trường sắp xếp trước đó (trường được dự kiến là ngẫu nhiên) không có tác dụng nên có lẽ luôn có cùng giá trị.
NEWID()
Tuy nhiên, việc đặt hàng bằng cách hoạt động, bởi vì nếu NEWID () không phải lúc nào cũng được đánh giá lại thì mục đích của UUID sẽ bị phá vỡ khi chèn nhiều hàng mới trong một sttnt với mã định danh duy nhất làm khóa, vì vậy:
SELECT display_name FROM tr_person ORDER BY NEWID()
không đặt tên "ngẫu nhiên".
DBMS khác
Điều trên đúng với MSSQL (ít nhất là năm 2005 và 2008, và nếu tôi nhớ đúng năm 2000). Một hàm trả về UUID mới phải được đánh giá mỗi lần trong tất cả các DBMS NEWID () nằm dưới MSSQL nhưng đáng để xác minh điều này trong tài liệu và / hoặc bằng các thử nghiệm của riêng bạn. Hành vi của các hàm kết quả tùy ý khác, như RAND (), có nhiều khả năng thay đổi giữa các DBMS, vì vậy hãy kiểm tra lại tài liệu.
Ngoài ra, tôi đã thấy việc đặt hàng theo các giá trị UUID bị bỏ qua trong một số ngữ cảnh vì DB cho rằng loại này không có thứ tự có ý nghĩa. Nếu bạn thấy đây là trường hợp đó, rõ ràng chuyển UUID thành một kiểu chuỗi trong mệnh đề thứ tự hoặc bọc một số hàm khác xung quanh nó như CHECKSUM()
trong SQL Server (có thể có một sự khác biệt nhỏ về hiệu năng này vì việc đặt hàng sẽ được thực hiện trên giá trị 32 bit không phải là giá trị 128 bit, mặc dù lợi ích của việc đó có cao hơn chi phí chạy CHECKSUM()
trên mỗi giá trị trước tiên tôi sẽ để bạn kiểm tra).
Lưu ý bên
Nếu bạn muốn một thứ tự tùy ý nhưng có thể lặp lại một chút, hãy sắp xếp theo một tập hợp con tương đối không được kiểm soát của dữ liệu trong các hàng. Chẳng hạn, một trong hai sẽ trả lại tên theo thứ tự tùy ý nhưng có thể lặp lại:
SELECT display_name FROM tr_person ORDER BY CHECKSUM(display_name), display_name -- order by the checksum of some of the row's data
SELECT display_name FROM tr_person ORDER BY SUBSTRING(display_name, LEN(display_name)/2, 128) -- order by part of the name field, but not in any an obviously recognisable order)
Các thứ tự tùy ý nhưng có thể lặp lại thường không hữu ích trong các ứng dụng, mặc dù có thể hữu ích trong việc kiểm tra nếu bạn muốn kiểm tra một số mã trên các kết quả theo nhiều đơn đặt hàng nhưng muốn có thể lặp lại mỗi lần chạy theo cùng một vài lần (để có được thời gian trung bình kết quả qua nhiều lần chạy hoặc kiểm tra rằng bản sửa lỗi bạn đã thực hiện đối với mã sẽ loại bỏ sự cố hoặc không hiệu quả được đánh dấu trước đó bởi một kết quả đầu vào cụ thể hoặc chỉ để kiểm tra rằng mã của bạn "ổn định" trong đó trả về cùng một kết quả mỗi lần nếu được gửi cùng một dữ liệu theo một thứ tự nhất định).
Thủ thuật này cũng có thể được sử dụng để có được kết quả tùy ý hơn từ các hàm, không cho phép các cuộc gọi không xác định như NEWID () trong cơ thể của chúng. Một lần nữa, đây không phải là thứ thường có ích trong thế giới thực nhưng có thể có ích nếu bạn muốn một hàm trả về một cái gì đó ngẫu nhiên và "Random-ish" là đủ tốt (nhưng hãy cẩn thận để nhớ các quy tắc xác định khi các hàm do người dùng xác định được tính toán, nghĩa là thường chỉ một lần trên mỗi hàng hoặc kết quả của bạn có thể không phải là những gì bạn mong đợi / yêu cầu).
Hiệu suất
Như EBarr chỉ ra, có thể có vấn đề về hiệu suất với bất kỳ vấn đề nào ở trên. Đối với nhiều hơn một vài hàng, bạn gần như chắc chắn sẽ thấy đầu ra được lưu vào tempdb trước khi số lượng hàng được yêu cầu được đọc lại theo đúng thứ tự, điều đó có nghĩa là ngay cả khi bạn đang tìm kiếm top 10, bạn vẫn có thể tìm thấy một chỉ mục đầy đủ quét (hoặc tệ hơn là quét bảng) xảy ra cùng với một khối lượng lớn ghi vào tempdb. Do đó, nó có thể cực kỳ quan trọng, như với hầu hết mọi thứ, để điểm chuẩn với dữ liệu thực tế trước khi sử dụng điều này trong sản xuất.