如何为关联table生成随机数据?

How to generate random data for association table?

我正在与三个 table 一起开发电子商店:productsatributesproduct_atributes。我已经填写了 tables productsatributes:

insert into atribute(name)
select random_atribute()
from generate_series(1,10000) as seq(i);

insert into product(price)
select floor(1 + random() * 100)::int
from generate_series(1,20000) as seq(i);

我想为table生成随机数据 product_atributes:1个产品可以有1个属性,但1个产品也可以有所有属性.结果应如下所示:

product_atributes
id  product_id     atribute_id
1      5               12
2      5               76
3      5               10
4      5                7
5      1               45
6      1               109
...

Table product_atributes 是这样创建的:

create table product_atributes(
  id serial primary key,
  atribute_id integer references atribute(id),
  product_id integer references product(id)
);

我试过了……像这样,但它不起作用:

with data as (
    select  s.i,
            random_atribute_id() as atribute_id,
            s.id as product_id
   
    from (generate_series(1, 1000) as seq(i)
             cross join lateral (select seq.i, * from product order by random() limit 1) as s)
)

insert into product_atributes(atribute_id, product_id)
select atribute_id, product_id from data;

我该怎么做?

简单

以 1% 的偶数概率插入所有可能的组合:

INSERT INTO product_atributes(product_id, atribut_id)
SELECT p.product_id, a.atribut_id
FROM   product p
JOIN   atribute a ON random() >= 0.99;

更复杂、更快

这提供了对最小和最大属性数量的更多控制。

并且快很多对于您的特定设置 gap-less 属性 ID(从 1 到 10000):

INSERT INTO product_atributes(product_id, atribut_id)
SELECT p.product_id, a.atribut_id
FROM  (SELECT product_id, trunc(random() * 10)::int AS ct FROM product) p
CROSS  JOIN LATERAL (
   SELECT DISTINCT 1 + trunc(random() * 10000) AS atribut_id
   FROM   generate_series (0, p.ct) g
   ) a;

这会为每个产品生成 0 到 10 个完全随机的关联。
2 + trunc(random() * 6)::int AS ct 会产生 3 到 8 个关联。 (注意从0开始的generate_series()!)

在子查询中生成属性 (ct) 的数量以避免对 random() 的单一评估导致所有产品的数量相同。

我们可以大大优化 gap-less ID 的性能。无需遍历每个产品的所有 10000 个属性,只需为给定的 ID 范围生成随机数。 快很多
投入 DISTINCT 以消除(不太可能的)重复项。对于 10000 中的 10 几乎无关紧要,但我们不允许重复。 (因此,在极少数情况下,可能获得较少的关联。)

我们甚至可以在有一些差距的情况下工作。选择随机行有很多微妙之处。参见:

  • Best way to select random rows PostgreSQL

旁白

您还可以使用 data-modifying CTEs 在单个查询中用随机数据填充所有三个表。 1:n 关系的简单示例:

与您的情况相同的原则,只是两个 CTE ...

相关:

  • How to implement a many-to-many relationship in PostgreSQL?

“属性”是这样写的