问题Mysql Random Row Query on Inner Join与我的问题大致相同,但从未得到解答。
我有一个主表m和一个从表s。 S每m包含1到许多行。我想要一个查询,该查询选择连接到恰好一个随机选择的从属的每个主行。
如果表模式为:
M
---
id
S
---
id
mid
然后,用伪代码查询将是:
select * from m inner join s on m.id = s.mid
,其中s.id
是从存在的值中随机选择的一个
可以将其转换为真实的SQL吗?
答案 0 :(得分:1)
我认为以下查询可完成所需的工作,但使用子查询(而非内部联接):
SELECT *, (SELECT id FROM S WHERE S.mid = M.id ORDER BY RAND() LIMIT 1) AS S_id
FROM M
这里是link进行测试。 希望对您有所帮助。
答案 1 :(得分:0)
这可以使用Row_Number()
概念来解决。我们需要在表mid
的{{1}}分区中随机分配行号值。然后,使用s
和m
从s
表到mid
的联接。每次都会选择一个随机行。
在低于8的MySQL版本中,我们可以使用User-defined Variables来仿真row_number = 1
。要了解其工作原理,您可以查看以下答案以获取解释:https://stackoverflow.com/a/53465139/2469308
请注意,该技术在大型表上比使用子查询(在Row_Number()
子句中)更为有效,因为它将对整个表进行一次排序。 strong>
SELECT
查询
create table m (id int, m_nm varchar(10));
create table s (id int,
mid int references m(mid),
s_nm varchar(10));
insert into m values(1, "a");
insert into m values(2, "b");
insert into m values(3, "c");
insert into s values(1, 1, "aa");
insert into s values(2, 1, "aa");
insert into s values(3, 2, "bb");
insert into s values(4, 2, "bbb");
insert into s values(5, 2, "bbbb");
insert into s values(6, 3, "cc");
insert into s values(7, 3, "ccc");
结果(运行#1)
SELECT
m.*, s_dt.id, s_dt.mid, s_dt.s_nm
FROM
m
JOIN
(
SELECT
@rn := IF(@m = dt.mid, @rn+1, 1) AS row_num,
@m := dt.mid AS mid,
dt.id,
dt.s_nm
FROM
(
SELECT
id, mid, s_nm, RAND() as rand_num
FROM s
ORDER BY mid, rand_num ) AS dt
CROSS JOIN (SELECT @rn:=0, @m:=0) AS user_vars
) AS s_dt
ON s_dt.mid = m.id AND
s_dt.row_num = 1;
结果(运行#2)
| id | m_nm | id | mid | s_nm |
| --- | ---- | --- | --- | ---- |
| 1 | a | 2 | 1 | aa |
| 2 | b | 5 | 2 | bbbb |
| 3 | c | 7 | 3 | ccc |
结果(运行#3)
| id | m_nm | id | mid | s_nm |
| --- | ---- | --- | --- | ---- |
| 1 | a | 1 | 1 | aa |
| 2 | b | 4 | 2 | bbb |
| 3 | c | 6 | 3 | cc |
MySQL 8.0.2+ / MariaDB 10.3 + 解决方案如下:
| id | m_nm | id | mid | s_nm |
| --- | ---- | --- | --- | ---- |
| 1 | a | 1 | 1 | aa |
| 2 | b | 3 | 2 | bb |
| 3 | c | 7 | 3 | ccc |