[英]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
中對INT
的CAST
與ROUND() function 所做的相同,這會導致錯誤。 FLOOR始終向下舍入,不會出現此問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.