postgresql 在Postgres表中插入虚拟数据

disbfnqx  于 2023-10-18  发布在  PostgreSQL
关注(0)|答案(3)|浏览(181)

下面是一个Postgres表:

  1. create table test (
  2. id serial,
  3. contract varchar,
  4. amount0 int,
  5. amount1 int,
  6. price double precision
  7. );

我想插入100行符合以下要求的虚拟数据:

  • 在“合同”列中,应该有“abc”、“klm”和“xyz”之外的值。
  • 在列“”0“和”“1”中,应该有50、60、80、100、200中的整数值。
  • 在“价格”列中,应该有1.5、1.8、2.1、2.5中的值。
    到目前为止,我得出的结论是:
  1. INSERT INTO test (amount0, amount1, price)
  2. SELECT
  3. (SELECT val FROM unnest(ARRAY[50, 60, 80, 100, 200]) AS val ORDER BY random() LIMIT 1),
  4. (SELECT val FROM unnest(ARRAY[50, 60, 80, 100, 200]) AS val ORDER BY random() LIMIT 1),
  5. (SELECT val FROM unnest(ARRAY[1.5, 1.8, 2.1, 2.5]) AS val ORDER BY random() LIMIT 1)
  6. FROM generate_series(1, 100);

但这并不管用。此语句始终只对列“price”使用“100”,对列“price”使用“50”,对列“price”使用“2.1”。
有人能帮帮我吗?

cfh9epnr

cfh9epnr1#

你可以随机下标选择数组:(demo

  1. INSERT INTO test (contract,amount0, amount1, price)
  2. SELECT (ARRAY['abc','klm','xyz'])[(random()*2+1)::int],
  3. (ARRAY[50, 60, 80, 100, 200])[(random()*4+1)::int],
  4. (ARRAY[50, 60, 80, 100, 200])[(random()*4+1)::int],
  5. (ARRAY[1.5, 1.8, 2.1, 2.5])[(random()*3+1)::int]
  6. FROM generate_series(1, 1e2, 1);
  7. SELECT id, contract,amount0, amount1, price FROM test LIMIT 6;

| ID|合同|联系我们|金额1|价格|
| --|--|--|--|--|
| 1 |KLM| 50 | 100 |2.1|
| 2 |xyz| 100 | 100 |1.5|
| 3 |ABC| 80 | 100 |1.8|
| 4 |xyz| 80 | 80 |2.1|
| 5 |xyz| 200 | 50 |1.8|
| 6 |xyz| 60 | 60 |1.8|
请注意,这是您打算做的,使每个选择独立随机。实际上,您很可能会得到重复的条目。如果你更喜欢不断获得独特的组合,直到你用完,然后才重新开始,你可以做一些类似于迈克的建议:(demo2

  1. INSERT INTO test (contract,amount0, amount1, price)
  2. SELECT contract,amount0, amount1, price
  3. FROM (values (50),(60),(80),(100),(200)) a(amount0),
  4. (values (50),(60),(80),(100),(200)) b(amount1),
  5. (values (1.5), (1.8), (2.1), (2.5)) c(price),
  6. (values ('abc'),('klm'),('xyz') ) d(contract),
  7. generate_series(1, 1e2, 1) duplicator(n)
  8. order by n, random()
  9. limit 100;

Here's a function如果你发现自己需要一个 * 加权 * 随机数,这意味着你想确切地定义一个选项与其他选项相比的可能性。
您的解决方案不起作用的原因是,由于标量子查询不以任何方式依赖于外部查询,因此它们只被计算一次并被重用。您可以通过使用explain analyze verbose运行它来检查计划。您可以通过添加外部引用来欺骗规划器,使其认为他们在某种程度上依赖于外部查询,即使它什么也不做(demo3),但上面的代码也是一样的,代码更少。

展开查看全部
piah890a

piah890a2#

问题是每次你运行你的命令时,PostgreSQL都会取一个种子号并将其发送给srand函数。这就是为什么使用相同的种子,您可以从数组中获得相同的值。因此,你需要调用函数,只要你想从数组中得到另一个值,你就可以创建函数。这将导致上下文切换,但这是我唯一能想到的。也许别人可以纠正我。代码如下:

  1. create table test (
  2. id serial,
  3. contract varchar,
  4. amount0 int,
  5. amount1 int,
  6. price double precision
  7. );
  8. CREATE OR REPLACE FUNCTION random_amount()
  9. RETURNS int
  10. LANGUAGE sql VOLATILE PARALLEL SAFE AS
  11. $func$
  12. SELECT ('[0:4]={50, 60, 80, 100, 200}'::int[])[trunc(random() * (4 - 1 + 1) + 1)::int];
  13. $func$;
  14. CREATE OR REPLACE FUNCTION random_price()
  15. RETURNS int
  16. LANGUAGE sql VOLATILE PARALLEL SAFE AS
  17. $func$
  18. (SELECT ('[0:3]={1.5, 1.8, 2.1, 2.5}'::float[])[trunc(random() * (3 - 1 + 1) + 1)::int]);
  19. $func$;
  20. INSERT INTO test (amount0, amount1, price)
  21. SELECT
  22. random_amount(), random_amount(), random_price()
  23. FROM generate_series(1, 100);
  24. select * from test;

Fiddle.

展开查看全部
k4emjkb1

k4emjkb13#

您的查询在正确的轨道上,可以为'price 0'、'price 1'和'price'列生成随机值。若要同时包含值为'abc'、'klm'和'xyz'的'contract'列,您可以按如下方式修改查询:

  1. INSERT INTO test (contract, amount0, amount1, price)
  2. SELECT
  3. CASE
  4. WHEN random() < 0.33 THEN 'abc'
  5. WHEN random() < 0.66 THEN 'klm'
  6. ELSE 'xyz'
  7. END AS contract,
  8. (SELECT val FROM unnest(ARRAY[50, 60, 80, 100, 200]) AS val ORDER BY random() LIMIT 1),
  9. (SELECT val FROM unnest(ARRAY[50, 60, 80, 100, 200]) AS val ORDER BY random() LIMIT 1),
  10. (SELECT val FROM unnest(ARRAY[1.5, 1.8, 2.1, 2.5]) AS val ORDER BY random() LIMIT 1)
  11. FROM generate_series(1, 100);
  12. SELECT id, contract, amount0, amount1, price FROM test LIMIT 6;

此查询使用CASE语句根据概率为“contract”列随机选择值。它为每一行分配概率大致相等的“abc”、“klm”或“xyz”。

相关问题