簡體   English   中英

使用 PostgreSQL 中列表中的值隨機填充表列

[英]Populate a table column randomly with values from a list in PostgreSQL

我想用以下值隨機填充表中的一列:可用、暫停、部分預付款、已售出/不可用、令牌

我曾嘗試使用以下命令,但它會用它獲得的第一個值填充整個列。

update mytable
set sold_status = (select (array['Available', 'On Hold', 'Partial Downpayment', 'Sold/Unavailable', 'Token Recieved'])[floor(random() * 5 + 1)])

我知道如何使用編程語言實現這一點,但我更喜歡 PostgreSQL 查詢來實現這一點。

Postgres 認為只運行一次random() () 對你有好處——忘記了random()是一個易失的 function。

您可以使用case解決此問題:

update mytable
    set sold_status = (case (random()*5)::int when 0 then 'Available' when 1 then 'On Hold' when 2 then 'Partial Downpayment' when 3 then 'Sold/Unavailable' when 4 then 'Token Recieved' end);

是一個 db<>fiddle。

雖然 PostgreSQL 跟蹤簡單表達式的波動性,但它不跟蹤不包含對外部查詢的引用的子選擇的波動性。 您可以通過引入對外部查詢的人工引用來解決此問題,但在您的情況下,您首先不需要子選擇,所以只需擺脫它。

update mytable
set sold_status = (array[
        'Available', 'On Hold', 'Partial Downpayment', 'Sold/Unavailable', 'Token Recieved'
    ]) [floor(random() * 5 + 1)];

由於此頁面的標題是"Populate a table column..." ,因此我將我的方法放在這里,以從列表的列中創建隨機值:

CREATE TABLE IF NOT EXISTS cars(
    id SERIAL PRIMARY KEY,
    brand VARCHAR(30)
);

INSERT INTO cars (
    brand
)
SELECT
    (array['BMW','AUDI','MERCEDES-BENZ'])[floor(random() * 3 + 1)]
FROM generate_series(1, 10);

它將使用品牌列表中的隨機值創建 10 行。

接受的答案不正確!

你可以在這里看到這個(下面的所有代碼都在這里):

CREATE TABLE tab AS
SELECT
  id,
  NULL AS rand_x5,
  NULL AS sold_status
FROM 
  generate_series(1, 10000) AS t(id);

然后運行:

WITH r AS
(
  SELECT j, (RANDOM() * 5)::INT AS x
  FROM GENERATE_SERIES(1, 10000) AS j
)
UPDATE tab
SET 
  rand_x5 = r.x, 
  sold_status =
  CASE r.x                   -- note different brackets (ranges - inclusive/exclusive boundaries)
    WHEN 0 THEN 'Available'  -- only happens from [0 - 0.5)    
    WHEN 1 THEN 'On Hold'    --      happens from [0.5 - 1.5) &c.
    WHEN 2 THEN 'Partial'
    WHEN 3 THEN 'Sold'
    WHEN 4 THEN 'Token'
  END 
FROM r
WHERE tab.id = r.j;

然后運行聚合查詢:

SELECT
  rand_x5, sold_status, COUNT(rand_x5), COUNT(sold_status)
FROM tab
GROUP by rand_x5, sold_status
ORDER BY rand_x5 DESC NULLS first;

結果:

rand_x5 sold_status count   count
      5        null  1047       0
      4       Token  2062    2062
      3        Sold  1995    1995
      2     Partial  1912    1912
      1     On Hold  2006    2006
      0   Available   978     978
SELECT 6   --  << 6 instead of 5

現在,這有兩個主要問題:

  • (RANDOM() * 5)::INT的 output 中有 6 個可能的值 (0 - 5),而不是 5 個。 由於您尚未處理CASE表達式中的 5,因此sold_status變為NULL

  • 第一個值 (0) 和最后一個 (5) 是傾斜的,因為如果生成大量值,它們將只有其他值 (1 - 4) 的 1/2 - 因為它們會僅在 0.5 的范圍內生成,而其他在 1 的范圍內生成

正確的代碼應該是FLOOR((RANDOM() * 5)) - 請參閱小提琴底部。 運行時的結果是:

rand_x5 sold_status count   count
0   Available   1938    1938
1   On Hold 2048    2048
2   Partial 1983    1983
3   Sold    2001    2001
4   Token   2030    2030

沒有NULL s 並且所有值(在合理范圍內)均等平衡! (RANDOM() * 5)::INT中對INTCASTROUND() function 所做的相同,這會導致錯誤。 FLOOR始終向下舍入,不會出現此問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM