从数据库中同时随机选择行是 SQL 中的一项常见任务,尤其是在处理大型数据集时。选择多行对于数据采样或生成用于分析的随机子集非常有用。在 MySQL 中,我们可以通过多种方法来实现这一目标,每种方法都有其优势。
在本文中,我们将探索在 MySQL 中从 60 万行数据集中检索 10 行随机记录的三种方法。我们将介绍它们的语法、示例和解释,帮助您深入了解如何高效地随机选择行。
在 MySQL 中从 60 万行数据中检索 10 个随机行
RAND() 函数是 SQL 中的一种函数,它帮助我们从表的现有数据中选择多行。让我们探讨一些选择多行的常用方法。常见的方法如下:
- 使用 RAND() 函数
- 使用主键进行随机选择
- 结合用户变量进行随机采样
设置环境
我们可以使用以下代码创建 Employee 表,该代码定义了包含 ‘empId‘、‘name‘ 和 ‘dept‘ 列的表结构。
创建 EMPLOYEE 表的查询:
CREATE TABLE EMPLOYEE (
empId INTEGER PRIMARY KEY,
name TEXT NOT NULL,
dept TEXT NOT NULL
);
向 EMPLOYEE 表中插入数据:
INSERT INTO EMPLOYEE VALUES (1, ‘Clark‘, ‘Sales‘);
INSERT INTO EMPLOYEE VALUES (2, ‘Dave‘, ‘Accounting‘);
INSERT INTO EMPLOYEE VALUES (3, ‘Ava‘, ‘Marketing‘);
INSERT INTO EMPLOYEE VALUES (4, ‘GFG‘, ‘Development‘);
INSERT INTO EMPLOYEE VALUES (5, ‘Adam‘, ‘Testing‘);
INSERT INTO EMPLOYEE VALUES (6, ‘Evan‘, ‘Operations‘);
INSERT INTO EMPLOYEE VALUES (7, ‘Avanya‘, ‘Accounting‘);
INSERT INTO EMPLOYEE VALUES (8, ‘Ziv‘, ‘Sales‘);
INSERT INTO EMPLOYEE VALUES (9, ‘Gia‘, ‘Development‘);
INSERT INTO EMPLOYEE VALUES (10, ‘Ele‘, ‘Testing‘);
INSERT INTO EMPLOYEE VALUES (11, ‘Jonas‘, ‘Operations‘);
INSERT INTO EMPLOYEE VALUES (12, ‘Hany‘, ‘Accounting‘);
INSERT INTO EMPLOYEE VALUES (13, ‘Sam‘, ‘Sales‘);
输出:
!employeeEmployee Table
1. 使用 RAND() 函数
选择随机行最简单、最直接的方法就是使用 RAND() 函数。该函数为每一行生成一个 0 到 1 之间的随机浮点值,允许我们对结果进行排序并限制选择数量。
语法:
> SELECT * FROM Table name
>
>
>
> ORDER BY RAND()
>
>
>
> LIMIT 10;
示例:为 Employee 表使用 RAND()
查询:
SELECT * FROM Employee
ORDER BY RAND()
LIMIT 10;
该查询从 EMPLOYEE 表中选择 10 个随机行。ORDER BY RAND() 子句使行顺序随机化,而 LIMIT 10 子句将输出限制为 10 行。
输出:
!Using RAND() function使用 RAND() 函数
解释: 该 SQL 查询从 Employee 表 中选择 10 个随机行,并按随机顺序排列。输出显示了这 10 行数据的随机排列结果。
2. 使用主键进行随机选择
如果表具有数值主键且间隙相对较少,我们可以利用它来实现更高效的随机选择。
语法:
> SELECT * FROM Table Name
>
>
>
> WHERE columnname >= (SELECT FLOOR(MAX(columnname) * RAND()) FROM Employee)
>
>
>
> ORDER BY column_name
>
>
>
> LIMIT 10;
示例:为 Employee 表使用主键
查询:
SELECT * FROM Employee
WHERE empId >= (SELECT FLOOR(MAX(empId) * RAND()) FROM Employee)
ORDER BY empId
LIMIT 10;
该查询基于 主键 随机选择一个起始点,并检索接下来的 10 行。
输出:
!2使用主键
解释: 该 SQL 查询通过设置一个最小 empId 值(该值等于表中最大 empId 和 0 之间随机生成的一个数)来从 Employee 表中选择 10 个随机行。然后,它按 empId 对选定的行进行排序。
3. 结合用户变量进行随机采样
为了对随机性进行更多控制,特别是在大型数据集中,我们可以使用用户变量为每一行分配一个随机数,然后基于这些数字进行选择。
语法:
> SET @row_number = 0;
>
>
>
> SELECT *
>
>
>
> FROM (
>
>
>
> SELECT *, (@rownumber:=@rownumber + 1) AS num
>
>
>
> FROM Table Name
>
>
>
> ORDER BY RAND()
>
>
>
> ) AS t
>
>
>
> WHERE num % (SELECT ROUND(COUNT(*) / 10) FROM Table Name) = 0
>
>
>
> LIMIT 10;
示例:为 Employee 表使用随机采样
查询:
SET @row_number = 0;
SELECT *
FROM (
SELECT *, (@row_number:=@row_number + 1) AS num
FROM Employee
ORDER BY RAND()
) AS t
WHERE num % (SELECT ROUND(COUNT(*) / 10) FROM Employee) = 0
LIMIT 10;
解释:
- INLINECODEca345c8f:首先初始化一个用户变量 INLINECODE028954ba 为 0。
- 内层查询:从 INLINECODEb14ca7fd 表中选择所有数据,使用 INLINECODEb97821ab 对数据进行随机排序,并利用变量 INLINECODE2012fc2e 为每一行生成一个递增的序号 INLINECODE3507cdb3。
- 外层查询:从内层查询的结果中筛选数据。
num % (SELECT ROUND(COUNT(*) / 10) FROM Employee) = 0这一条件通过取模运算,试图以近似均匀的间隔从随机排序后的数据中抽取行。 -
LIMIT 10:最终只返回 10 行数据。
这种方法结合了变量的顺序控制和随机排序,旨在提供一种不同于直接排序取前 N 行的随机采样思路。
结论
在本文中,我们探讨了三种不同的方法,用于从大型 MySQL 数据集中随机选择 10 个行。每种方法都有其适用场景:
- 使用 RAND() 函数:最简单直接,适合中小规模数据表。在数据量极大(如 60 万行)时,由于需要对全表进行排序,可能会导致性能下降。
- 使用主键进行随机选择:如果主键是连续的数字且分布均匀,这种方法效率较高。它避免了全表排序,而是通过计算随机起始点来选取数据,但需要主键列建立索引。
- 结合用户变量进行随机采样:提供了更灵活的控制,通过随机打乱顺序并结合取模算法进行采样。这种方法逻辑较复杂,但在某些特定场景下(如需要特定的采样间隔)可能有用。
选择哪种方法取决于具体的表结构、数据量大小以及对性能的要求。通过理解这些方法的内部机制,我们可以做出更明智的决策,以优化数据库查询性能。