首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

各主流資料庫隨機查詢 SQL 寫法大全:MySQL/Oracle/SQL Server/Access

     編輯:MySQL 資料庫相關知識

隨機查詢核心挑戰

資料庫無原生「隨機排序」功能,需借助隨機函數產生亂數欄位再排序。不同資料庫函數名稱、語法差異大,且大量資料排序效能極差,需根據資料量選擇策略。

四大主流資料庫標準寫法

資料庫語法範例(取 10 筆)隨機函數
MySQLORDER BY RAND() LIMIT NSELECT * FROM users ORDER BY RAND() LIMIT 10;RAND() 回傳 0~1 浮點數
PostgreSQLORDER BY RANDOM() LIMIT NSELECT * FROM users ORDER BY RANDOM() LIMIT 10;RANDOM()
SQL ServerORDER BY NEWID()SELECT TOP 10 * FROM users ORDER BY NEWID();NEWID() 產生 GUID
OracleORDER BY DBMS_RANDOM.VALUESELECT * FROM (SELECT * FROM users ORDER BY DBMS_RANDOM.VALUE) WHERE ROWNUM <= 10;DBMS_RANDOM.VALUE
AccessORDER BY RND(欄位)SELECT TOP 10 * FROM users ORDER BY RND(id);RND() 需種子
SQLiteORDER BY RANDOM() LIMIT NSELECT * FROM users ORDER BY RANDOM() LIMIT 10;RANDOM()

Access 特殊寫法說明

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)。百萬行資料查詢可達秒級甚至掛起。

優化策略一:主鍵範圍隨機(適用自增 ID、無大量刪除空洞)

-- 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";

優化策略三:隨機主鍵 ID 列表法(極大表、需精確分布)

-- 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);

優化策略四:TABLESAMPLE(PostgreSQL 9.5+、SQL Server、Oracle 12c+)

-- PostgreSQL
SELECT * FROM users TABLESAMPLE BERNOULLI (0.1);  -- 0.1% 採樣

-- SQL Server
SELECT * FROM users TABLESAMPLE (10 ROWS);

系統層面採樣,不走全表排序,極快但非精確行數、可能重複。

實務選擇決策樹

  1. 資料量 < 1 萬行 → 直接 ORDER BY RAND()/RANDOM()/NEWID() 最簡單。
  2. 1 萬 ~ 100 萬行、自增 ID 連續 → 主鍵範圍隨機或兩次查詢法。
  3. 100 萬行以上、需精確均勻分布 → 隨機主鍵 ID 列表法(配合 Redis 快取 ID 列表)。
  4. 統計分析、近似結果可接受 → TABLESAMPLE 或 BERNOULLI 採樣。
  5. 極高頻隨機需求 → 離線預計算隨機排序結果表,定期重建。

常見誤區

  • ORDER BY RAND() 加上 WHERE 條件不會減少排序行數(先 WHERE 後 ORDER BY,但仍需對結果集排序)。
  • 使用 UUID() 或 MD5(RAND()) 當排序鍵,效能同 RAND() 且佔用更大。
  • Access/Jet 引擎隨機函數行為不穩定,建議遷移至 SQLite/PostgreSQL。

總結

隨機查詢看似簡單,大量資料下是效能殺手。掌握各資料庫原生語法只是入門,關鍵在於根據資料量級選擇正確策略:小表直排、中表偏移、大表預計算、統計採樣。應用層產生隨機數配合 LIMIT offset, N 是最通用、高效的工程化方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved