我已经为Microsoft SQL Server和PostGresql提出了类似的问题。在那里工作的解决方案不适用于MySQL。
我有两个表,stuff
和nonsense
。我想将nonsense
中随机行中的多个值复制到stuff
中的每一行。当然,会有重复。
STUFF
+----+---------+-------------+--------+
| id | details | data | more |
+====+=========+=============+========+
| 1 | one | (null) | (null) |
| 2 | two | (null) | (null) |
| 3 | three | (null) | (null) |
| 4 | four | (null) | (null) |
| 5 | five | (null) | (null) |
| 6 | six | (null) | (null) |
+----+---------+-------------+--------+
NONSENSE
+----+---------+-------------+
| id | data | more |
+====+=========+=============+
| 1 | apple | accordion |
| 2 | banana | banjo |
| 3 | cherry | cor anglais |
+----+---------+-------------+
我希望能够将这些内容复制到stuff
表中:
UPDATE stuff SET data=?,more=?
FROM ?
我想得到以下内容:
+-----+----------+---------+-------------+
| id | details | data | more |
+=====+==========+=========+=============+
| 1 | one | banana | banjo |
| 2 | two | apple | accordion |
| 3 | three | apple | accordion |
| 4 | four | cherry | cor anglais |
| 5 | five | banana | banjo |
| 6 | six | cherry | cor anglais |
+-----+----------+---------+-------------+
这是一个适用于PostgreSQL的小提琴:http://sqlfiddle.com/#!17/313fb/8
如果它是单个值,我可以使用相关子查询,但它对于来自同一行的多个值不能正常工作。
较新的PostGresql可以从相关子查询中复制到多个列。 SQL Server OUTER APPLY
子句,它允许FROM子句中的子查询相关。这两种方法都不适用于MySQL。
如何从另一个表中的随机行复制多个值?
答案 0 :(得分:1)
不是很好看,但我认为这是一个解决方案。
从包含stuff.id
和随机nonsense.id
:
select id,(select id from nonsense order by rand() limit 1) as nid from stuff;
使用此虚拟表作为子查询加入stuff
表:
stuff s
join
(select id,(select id from nonsense order by rand() limit 1) as nid from stuff) sq
on s.id=sq.id
使用相关子查询更新s.data
和s.more
:
set
s.data=(select data from nonsense where id=sq.nid),
s.more=(select more from nonsense where id=sq.nid);
这给出了:
update
stuff s
join
(select id,(select id from nonsense order by rand() limit 1) as nid from stuff) sq
on s.id=sq.id
set
s.data=(select data from nonsense where id=sq.nid),
s.more=(select more from nonsense where id=sq.nid);
应该有一个更顺畅的解决方案,但这是我能做的最好的。
答案 1 :(得分:0)
如果你只需要做一次并且不关心真正的随机,也许发明一个函数,它以某种方式将stuff.id映射到nonsense.id? 例如:
update stuff s, nonsense n
set s.data = n.data, s.more = n.more
where n.id = s.id + 1 or n.id = ceil(s.id/2) -1;
对我来说看起来很像疯狂;)
http://sqlfiddle.com/#!9/dd0935/1
P.S。现在,认真......不能在sqlfiddle上试试,但是如果你有权访问mysql 8.0+版,你可以试试如下的smth:
with rn as (select n.data, n.more from stuff s, nonsense n order by rand())
update stuff, rn
set stuff.data = rn.data, stuff.more = rn.more;
更新:经过一些协作性脑力激荡后,发现了另外两个变种
update stuff s
join (select id,(select id from nonsense order by rand() limit 1) as nid from stuff) sq on s.id=sq.id
join nonsense n on n.id = sq.nid
set s.data = n.data, s.more = n.more;
update stuff s
join (select * from (select s.id as sid, n.data as sdata, n.more as smore from stuff s, nonsense n order by rand()) sn group by sn.sid) sgr on s.id = sgr.sid
set s.data = sgr.sdata, s.more = sgr.smore;