Làm thế nào để chọn ngẫu nhiên các hàng trong SQL?


226

Tôi đang sử dụng MSSQL Server 2005. Trong db của tôi, tôi có một bảng "customerNames" có hai cột "Id" và "Name" và khoảng. 1.000 kết quả.

Tôi đang tạo một chức năng trong đó tôi phải chọn ngẫu nhiên 5 khách hàng mỗi lần. Ai đó có thể cho tôi biết cách tạo một truy vấn sẽ nhận được 5 hàng ngẫu nhiên (Id và Tên) mỗi khi thực hiện truy vấn không?


Ngẫu nhiên không phải là một yêu cầu chung đối với Cơ sở dữ liệu, tôi đã rất ngạc nhiên khi tìm thấy một liên kết cho một số SQL
Paxic

2
Phụ thuộc vào mức độ ngẫu nhiên mà bạn muốn. Xem: msdn.microsoft.com/en-us/l Library / aa175776 (MySQL.80) .aspx để so sánh NEW_ID so với RAND ()
Shannon Severance

Câu trả lời:


639
SELECT TOP 5 Id, Name FROM customerNames
ORDER BY NEWID()

Điều đó nói rằng, mọi người dường như đến trang này để có câu trả lời chung hơn cho câu hỏi của bạn:

Chọn một hàng ngẫu nhiên trong SQL

Chọn một hàng ngẫu nhiên với MySQL:

SELECT column FROM table
ORDER BY RAND()
LIMIT 1

Chọn một hàng ngẫu nhiên với PostgreSQL:

SELECT column FROM table
ORDER BY RANDOM()
LIMIT 1

Chọn một hàng ngẫu nhiên với Microsoft SQL Server:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

Chọn một hàng ngẫu nhiên với IBM DB2

SELECT column, RAND() as IDX 
FROM table 
ORDER BY IDX FETCH FIRST 1 ROWS ONLY

Chọn một bản ghi ngẫu nhiên với Oracle:

SELECT column FROM
( SELECT column FROM table
ORDER BY dbms_random.value )
WHERE rownum = 1

Chọn một hàng ngẫu nhiên với sqlite:

SELECT column FROM table 
ORDER BY RANDOM() LIMIT 1

3
+1 để đăng câu trả lời trực tiếp trên SO thay vì liên kết đến một trang web bên ngoài (như câu trả lời được chấp nhận) có thể đã bị hỏng khi người dùng trong tương lai nhìn vào câu hỏi này.
Ray Zhou

17
Điều này có trở nên rất đắt đỏ trên các bảng lớn, trong đó mỗi hàng có một số ngẫu nhiên và sau đó một bộ số ngẫu nhiên lớn không được lập trình được sắp xếp không?
Andrey

Điều này có lẽ rõ ràng với hầu hết mọi người, nhưng đối với tôi thì không rõ ràng ... truy vấn sau sẽ không nhận được giá trị ngẫu nhiên mới cho mỗi hàng: update tbl_vouchers set tbl_UsersID = (select top(1) id from tbl_Users order by NEWID()) - chỉnh sửa: Tôi không thể định dạng để hoạt động trong các nhận xét :(
Mir

Bạn thiên tài! Tôi ghét bạn rất nhiều vì tôi đã không nhìn thấy điều này cho đến khi tôi đi và viết một truy vấn cực kỳ dài với các truy vấn phụ và số hàng.
greenkode

5
Cảnh báo: Đối với cơ sở dữ liệu lớn, phương pháp này sẽ có hiệu suất kém. Bạn có thể tưởng tượng thời gian cần thiết để tạo một giá trị ngẫu nhiên cho mỗi hàng nếu cơ sở dữ liệu có một triệu mục nhập không? Bạn có thể có thêm thông tin về và một lựa chọn tốt hơn ở đây .
Francis Ngueukam


11

Trong trường hợp ai đó muốn một giải pháp PostgreSQL:

select id, name
from customer
order by random()
limit 5;

Câu trả lời này là tốt cho PostgreSQL, nó không cần giới hạn.
bí danh

9

Có lẽ trang web này sẽ được hỗ trợ.

Đối với những người không muốn nhấp qua:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

2
nên có ít nhất thay thế 1 bằng 5 :)
roman m


5

Nếu bạn có một bảng có hàng triệu hàng và quan tâm đến hiệu suất, đây có thể là một câu trả lời tốt hơn:

SELECT * FROM Table1
WHERE (ABS(CAST(
  (BINARY_CHECKSUM
  (keycol1, NEWID())) as int))
  % 100) < 10

https://msdn.microsoft.com/en-us/l Library / cc441928.aspx


Lưu ý rằng điều này sẽ chọn khoảng 10% các hàng trong bảng. Nếu bạn cần chọn một số lượng chính xác của hàng hoặc ít nhất là N hàng, phương pháp này sẽ không hiệu quả.
LarsH

4

Đây là một câu hỏi cũ, nhưng cố gắng áp dụng một trường mới (NEWID () hoặc ORDER BY rand ()) cho một bảng có số lượng lớn các hàng sẽ rất tốn kém. Nếu bạn có ID gia tăng, ID duy nhất (và không có bất kỳ lỗ hổng nào), sẽ hiệu quả hơn khi tính X # ID được chọn thay vì áp dụng GUID hoặc tương tự với mỗi hàng đơn lẻ và sau đó lấy X # trên cùng.

DECLARE @minValue int;
DECLARE @maxValue int;
SELECT @minValue = min(id), @maxValue = max(id) from [TABLE];

DECLARE @randomId1 int, @randomId2 int, @randomId3 int, @randomId4 int, @randomId5 int
SET @randomId1 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId2 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId3 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId4 = ((@maxValue + 1) - @minValue) * Rand() + @minValue
SET @randomId5 = ((@maxValue + 1) - @minValue) * Rand() + @minValue

--select @maxValue as MaxValue, @minValue as MinValue
--  , @randomId1 as SelectedId1
--  , @randomId2 as SelectedId2
--  , @randomId3 as SelectedId3
--  , @randomId4 as SelectedId4
--  , @randomId5 as SelectedId5

select * from [TABLE] el
where el.id in (@randomId1, @randomId2, @randomId3, @randomId4, @randomId5)

Nếu bạn muốn chọn nhiều hàng hơn, tôi sẽ xem xét việc điền #tempTable với ID và một loạt các giá trị rand () sau đó sử dụng từng giá trị rand () để chia tỷ lệ thành các giá trị tối thiểu. Bằng cách đó, bạn không phải xác định tất cả các tham số @ RandomId1 ... n. Tôi đã bao gồm một ví dụ dưới đây bằng cách sử dụng CTE để điền vào bảng ban đầu.

DECLARE @NumItems int = 100;

DECLARE @minValue int;
DECLARE @maxValue int;
SELECT @minValue = min(id), @maxValue = max(id) from [TABLE];
DECLARE @range int = @maxValue+1 - @minValue;

with cte (n) as (
   select 1 union all
   select n+1 from cte
   where n < @NumItems
)
select cast( @range * rand(cast(newid() as varbinary(100))) + @minValue as int) tp
into #Nt
from cte;

select * from #Nt ntt
inner join [TABLE] i on i.id = ntt.tp;

drop table #Nt;

@Protigupt, bản chỉnh sửa bạn đề xuất đã phá vỡ lựa chọn ngẫu nhiên. Sử dụng min () và max () được áp dụng cho bảng dbo.Tally64k sẽ không cho phép người dùng chọn một hàng có id pk> 65556.
RIanGillis

Thay đổi tên bảng chỉ đơn giản là một tạo tác từ thử nghiệm. Tên bảng thực tế không quan trọng, miễn là sử dụng đúng bảng. cả min () và max () đều có thể được truy vấn trong một truy vấn chứ không phải hai, đó là những gì tôi đang cố gắng thể hiện.
Bảo vệ

@Protigupt Ah, tôi thấy rằng bây giờ, tôi đã bối rối vì bạn đã sử dụng 0-65k khi thực hiện min-max nhưng không muộn hơn. Sau lần chỉnh sửa gần đây nhất của bạn, tôi thực sự muốn hỏi bạn về ý nghĩa hiệu suất của những thay đổi bạn đã thực hiện, vì điều chỉnh hiệu suất là một trong những sở thích của tôi và những quyết định dường như vô nghĩa như bên nào của dấu bằng bạn đặt một thứ gì đó thực sự có thể có tác động đáng kể - - Điều tương tự có áp dụng cho các cuộc gọi 5 SET @ RandomId ## không? Hoặc là khác nhau bởi vì nó không CHỌN TỪ một bảng thực tế?
RIanGillis

Tôi không chắc là tôi hiểu câu hỏi của bạn. Bạn có hỏi tại sao có 5 BỘ thay vì chỉ 1 CHỌN @ id1 = rand (), @ id2 = rand () ..? Đó là bởi vì nhiều lệnh gọi đến một câu lệnh rand () trong 1 sẽ tạo ra cùng một kết quả, do đó SET được phân tách. (rand () trên SQL Server là một hàm xác định, tôi tin vậy.) Tôi đoán rằng 1 select vs 5 set nằm trong phạm vi hiệu suất nano giây.
Ngày

4
SELECT * FROM TABLENAME ORDER BY random() LIMIT 5; 

Câu hỏi cũ, nhưng câu trả lời này không chạy cho tôi trong Oracle.
Gấu

CHỌN * TỪ (CHỌN * TỪ bảng ĐẶT HÀNG B DBNG DBMS_RANDOM.VALUE) WHERE rownum <number; @ Hãy thử cái này
Narendra

3

Tôi đã tìm thấy điều này để làm việc tốt nhất cho dữ liệu lớn.

SELECT TOP 1 Column_Name FROM dbo.Table TABLESAMPLE(1 PERCENT);

TABLESAMPLE(n ROWS) or TABLESAMPLE(n PERCENT)là ngẫu nhiên nhưng cần thêm TOP nđể có được kích thước mẫu chính xác.

Sử dụng NEWID()rất chậm trên các bàn lớn.


0

Như tôi đã giải thích trong bài viết này , để xáo trộn tập kết quả SQL, bạn cần sử dụng lệnh gọi hàm cụ thể cho cơ sở dữ liệu.

Lưu ý rằng việc sắp xếp một tập kết quả lớn bằng hàm RANDOM có thể rất chậm, vì vậy hãy đảm bảo bạn làm điều đó trên các tập kết quả nhỏ.

Nếu bạn phải xáo trộn một tập kết quả lớn và hạn chế nó sau đó, sau đó nó là tốt hơn để một cái gì đó sử dụng như OracleSAMPLE(N) hoặc TABLESAMPLEtrong SQL Server hoặc PostgreSQL thay vì một hàm ngẫu nhiên trong mệnh đề ORDER BY.

Vì vậy, giả sử chúng ta có bảng cơ sở dữ liệu sau:

nhập mô tả hình ảnh ở đây

Và các hàng sau trong songbảng:

| id | artist                          | title                              |
|----|---------------------------------|------------------------------------|
| 1  | Miyagi & Эндшпиль ft. Рем Дигга | I Got Love                         |
| 2  | HAIM                            | Don't Save Me (Cyril Hahn Remix)   |
| 3  | 2Pac ft. DMX                    | Rise Of A Champion (GalilHD Remix) |
| 4  | Ed Sheeran & Passenger          | No Diggity (Kygo Remix)            |
| 5  | JP Cooper ft. Mali-Koa          | All This Love                      |

Oracle

Trên Oracle, bạn cần sử dụng DBMS_RANDOM.VALUEhàm, như được minh họa bằng ví dụ sau:

SELECT
    artist||' - '||title AS song
FROM song
ORDER BY DBMS_RANDOM.VALUE

Khi chạy truy vấn SQL đã nói ở trên trên Oracle, chúng ta sẽ nhận được tập kết quả sau:

| song                                              |
|---------------------------------------------------|
| JP Cooper ft. Mali-Koa - All This Love            |
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |

Lưu ý rằng các bài hát đang được liệt kê theo thứ tự ngẫu nhiên, nhờ DBMS_RANDOM.VALUElệnh gọi hàm được sử dụng bởi mệnh đề ORDER BY.

Máy chủ SQL

Trên SQL Server, bạn cần sử dụng NEWIDhàm, như được minh họa bằng ví dụ sau:

SELECT
    CONCAT(CONCAT(artist, ' - '), title) AS song
FROM song
ORDER BY NEWID()

Khi chạy truy vấn SQL đã nói ở trên trên SQL Server, chúng ta sẽ nhận được tập kết quả sau:

| song                                              |
|---------------------------------------------------|
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |
| JP Cooper ft. Mali-Koa - All This Love            |
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |

Lưu ý rằng các bài hát đang được liệt kê theo thứ tự ngẫu nhiên, nhờ NEWIDlệnh gọi hàm được sử dụng bởi mệnh đề ORDER BY.

PostgreSQL

Trên PostgreSQL, bạn cần sử dụng randomhàm, như được minh họa bằng ví dụ sau:

SELECT
    artist||' - '||title AS song
FROM song
ORDER BY random()

Khi chạy truy vấn SQL đã nói ở trên trên PostgreSQL, chúng ta sẽ nhận được tập kết quả sau:

| song                                              |
|---------------------------------------------------|
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |
| JP Cooper ft. Mali-Koa - All This Love            |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |

Lưu ý rằng các bài hát đang được liệt kê theo thứ tự ngẫu nhiên, nhờ randomlệnh gọi hàm được sử dụng bởi mệnh đề ORDER BY.

MySQL

Trên MySQL, bạn cần sử dụng RANDhàm, như được minh họa bằng ví dụ sau:

SELECT
  CONCAT(CONCAT(artist, ' - '), title) AS song
FROM song
ORDER BY RAND()

Khi chạy truy vấn SQL đã nói ở trên trên MySQL, chúng ta sẽ nhận được tập kết quả sau:

| song                                              |
|---------------------------------------------------|
| HAIM - Don't Save Me (Cyril Hahn Remix)           |
| Ed Sheeran & Passenger - No Diggity (Kygo Remix)  |
| Miyagi & Эндшпиль ft. Рем Дигга - I Got Love      |
| 2Pac ft. DMX - Rise Of A Champion (GalilHD Remix) |
| JP Cooper ft. Mali-Koa - All This Love            |

Lưu ý rằng các bài hát đang được liệt kê theo thứ tự ngẫu nhiên, nhờ RANDlệnh gọi hàm được sử dụng bởi mệnh đề ORDER BY.


0

Nếu bạn đang sử dụng bảng lớn và muốn truy cập 10 phần trăm dữ liệu thì hãy chạy lệnh sau: SELECT TOP 10 PERCENT * FROM Table1 ORDER BY NEWID();

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.