資料庫無原生「隨機排序」功能,需借助隨機函數產生亂數欄位再排序。不同資料庫函數名稱、語法差異大,且大量資料排序效能極差,需根據資料量選擇策略。
| 資料庫 | 語法 | 範例(取 10 筆) | 隨機函數 |
|---|---|---|---|
| MySQL | ORDER BY RAND() LIMIT N | SELECT * FROM users ORDER BY RAND() LIMIT 10; | RAND() 回傳 0~1 浮點數 |
| PostgreSQL | ORDER BY RANDOM() LIMIT N | SELECT * FROM users ORDER BY RANDOM() LIMIT 10; | RANDOM() |
| SQL Server | ORDER BY NEWID() | SELECT TOP 10 * FROM users ORDER BY NEWID(); | NEWID() 產生 GUID |
| Oracle | ORDER BY DBMS_RANDOM.VALUE | SELECT * FROM (SELECT * FROM users ORDER BY DBMS_RANDOM.VALUE) WHERE ROWNUM <= 10; | DBMS_RANDOM.VALUE |
| Access | ORDER BY RND(欄位) | SELECT TOP 10 * FROM users ORDER BY RND(id); | RND() 需種子 |
| SQLite | ORDER BY RANDOM() LIMIT N | SELECT * FROM users ORDER BY RANDOM() LIMIT 10; | RANDOM() |
Access RND() 需傳入數值種子,常用自動編號欄位:
Dim r
Randomize
r = Rnd
sql = "SELECT TOP 10 * FROM table ORDER BY RND(" & r & "-id)"
' 或使用其他數值欄位
sql = "SELECT TOP 10 * FROM table ORDER BY RND(" & r & "-Len(UserName))"
ORDER BY RAND() 會為每行產生亂數、建立臨時表、檔案排序,複雜度 O(N log N)。百萬行資料查詢可達秒級甚至掛起。
-- MySQL 範例
SELECT * FROM users
WHERE id >= (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM users)))
ORDER BY id LIMIT 10;
原理:隨機取一個起始 ID,向後取 N 筆。極快但分布不均勻(ID 密集區機率高)。
-- 步驟 1:取得總行數
SELECT COUNT(*) INTO @total FROM users;
-- 步驟 2:應用層產生隨機 offset
SET @offset = FLOOR(RAND() * @total);
-- 步驟 3:查詢
PREPARE stmt FROM 'SELECT * FROM users LIMIT ?, 10';
EXECUTE stmt USING @offset;
應用層(PHP/Java/Go)產生隨機 offset 更簡潔:
$offset = mt_rand(0, $total - 1);
$sql = "SELECT * FROM users LIMIT $offset, 10";
-- 1. 建立只含主鍵的輕量表/視圖/物化視圖
CREATE TABLE user_ids AS SELECT id FROM users;
-- 2. 從輕量表隨機取 ID(配合策略二)
SELECT id FROM user_ids ORDER BY RAND() LIMIT 10;
-- 3. 應用層收集 ID 列表,再主查詢
SELECT * FROM users WHERE id IN (id1, id2, ..., id10);
-- PostgreSQL
SELECT * FROM users TABLESAMPLE BERNOULLI (0.1); -- 0.1% 採樣
-- SQL Server
SELECT * FROM users TABLESAMPLE (10 ROWS);
系統層面採樣,不走全表排序,極快但非精確行數、可能重複。
ORDER BY RAND()/RANDOM()/NEWID() 最簡單。TABLESAMPLE 或 BERNOULLI 採樣。ORDER BY RAND() 加上 WHERE 條件不會減少排序行數(先 WHERE 後 ORDER BY,但仍需對結果集排序)。UUID() 或 MD5(RAND()) 當排序鍵,效能同 RAND() 且佔用更大。隨機查詢看似簡單,大量資料下是效能殺手。掌握各資料庫原生語法只是入門,關鍵在於根據資料量級選擇正確策略:小表直排、中表偏移、大表預計算、統計採樣。應用層產生隨機數配合 LIMIT offset, N 是最通用、高效的工程化方案。