我必须创建一个虚拟数据。我在'buildings'表中已经具有30000多个要素,并创建了1个新列'roof_material'。 我还有另一个名为“ materials”的表,其中包含8行,如下所示:
|id| material
+--+-----------
|1 | tiles
|2 | metal
|3 | concrete
|4 | slate
|5 | steel
|6 | clay
|7 | wood shake
|8 | asphalt
我想用“材料”表中的值随机填充building.roof_materials。
最后,这30000个要素中的每一行都将具有roof_materials数据。
有人可以帮助我吗?
答案 0 :(得分:1)
假设列roof_material
是material
表的外键,您可以简单地执行以下操作:
update buildings
set roof_material = (random() * 7 + 1)::int;
从本质上讲,这是对material
表的可能主键值进行硬编码的方法-对于一次更新就足够了。
如果您想根据material
表中的 actual 值来使它动态化,则可以使用以下方法:
with idlist as (
select array_agg(id) mat_ids
from material
)
update building
set roof_material = mat_ids[(random() * (cardinality(mat_ids) - 1) + 1)::int]
from idlist;
首先common table expression idlist
将material
表中所有现有的ID收集到一个数组中,然后update语句在更新建筑表时从该数组中随机选择元素。
答案 1 :(得分:0)
这可能很棘手,因为有时Postgres优化会遇到麻烦。一种方法使用横向联接(或相关子查询):
select gs.x, m.*
from generate_series(1, 100) gs(x) cross join lateral
(select m.*
from materials m
where gs.x is not null
order by random()
) m
相关子句(where
)很重要,因为否则Postgres决定它只能运行一次子查询。
如果您希望值的均等分布,则可以随机枚举每个列表,并使用取模算法将它们连接起来:
with t as (
select gs.x, row_number() over (order by random()) - 1 as seqnum
from generate_series(1, 100) gs(x)
),
m as (
select m.*, row_number() over (order by random()) - 1 as seqnum,
count(*) over () as num_materials
from materials m
)
select t.x, m.id, m.material
from t join
m
on t.seqnum % m.num_materials = m.seqnum
order by t.x;
Here是db <>小提琴。