PDA

View Full Version : Lấy Một Số Bản Ghi Ngẫu Nhiên



vuht2000
24-08-2010, 22:42
Khi bạn cần lấy về ngẫu nhiên một số bản ghi trong bảng (ví dụ để hiện một bài báo ngẫu nhiên trên trang web, hoặc khi bạn muốn xem qua bằng mắt thường xem dữ liệu có vấn đề gì không), bạn có thể dùng đoạn code sau:

SELECT TOP 5 *
FROM dbo.Tblxyz
ORDER BY NEWID()

Hàm NEWID() mỗi lần được gọi trả về một giá trị kiểu uniqueidentifier bất kỳ và duy nhất, vì thế mệnh đề ORDER BY NEWID() giúp cho câu lệnh chọn ra 5 bản ghi hoàn toàn ngẫu nhiên.

Một tình huống phức tạp hơn là khi bạn cần lấy về một số bản ghi ngẫu nhiên cho mỗi “chủng loại”. Ví dụ bạn có khách hàng từ tất cả các tỉnh thành trong cả nước, và từ mỗi tỉnh thành bạn muốn lấy về ngẫu nhiên 5 khách hàng. Bạn có thể dùng kết hợp hàm NEWID() với hàm ROW_NUMBER() để thực hiện điều trên (hàm ROW_NUMBER() mới được đưa vào SQL Server 2005 nên bạn không thể dùng cách làm này với bản 2000). Ở ví dụ dưới đây tôi dùng bảng Sales.Customer trong database AdventureWorks và muốn lấy về 2 khách hàng ngẫu nhiên đến từ mỗi vùng lãnh thổ (TerritoryID). Trước hết là lấy về các CustomerID ngẫu nhiên theo yêu cầu:

SELECT CustomerID, ROW_NUMBER() OVER (PARTITION BY TerritoryID ORDER BY NEWID()) AS ID
FROM Sales.Customer

Hàm ROW_NUMBER() khi không có lựa chọn nào sẽ trả về một dãy số tuần tự 1,2,3,4… khi có lựa chọn PARTITION BY TerritoryID nó sẽ reset lại dãy số cho mỗi TerritoryID, do đó mỗi khi gặp TerritoryID mới thì dãy số sẽ lại bắt đầu từ 1,2,3… Thêm nữa mệnh đề ORDER BY NEWID() làm cho bên trong mỗi TerritoryID các bản ghi được sắp xếp theo một cách ngẫu nhiên. Vì thế việc tiếp theo đơn giản là lấy hai bản ghi đầu (ID = 1 và 2) và JOIN với bảng chính để lấy các trường dữ liệu cần thiết:

SELECT C.*
FROM Sales.Customer C
JOIN (SELECT CustomerID, ROW_NUMBER() OVER (PARTITION BY TerritoryID ORDER BY NEWID()) AS ID
FROM Sales.Customer) RC -- Random Customer
ON C.CustomerID = RC.CustomerID
WHERE RC.ID <= 2
ORDER BY C.TerritoryID, C.CustomerID