我在postgresql中有一个带有两列的表:原始ID和重复ID。
样本数据:
original_id duplicate_id
1 1
2 2
3 3
4 4
5 5
6 6
我想将此表格随机分成50/50,因此我可以在每个表格中放置一个特定的标签
样本数据:
original_id duplicate_id tag
1 1 control
2 2 treatment
3 3 treatment
4 4 control
5 5 treatment
6 6 control
重要的是: 1.选择必须是随机的 2.拆分必须为50/50(如果行数为奇数,则为最接近的拆分)
答案 0 :(得分:0)
您可以使用此查询以随机顺序选择一半的行:
select *
from my_table
order by random()
limit (select count(*)/ 2 from my_table)
使用它来标记行:
with control as (
select *
from my_table
order by random()
limit (select count(*)/ 2 from my_table)
)
select
*,
case when t in (select t from control t) then 'control' else 'treatment' end
from my_table t;
答案 1 :(得分:0)
您可以使用rownumber() OVER (ORDER BY random())
为每个记录分配一个随机数。然后在CASE
中使用它来分配标签'control'
或'treatment'
,具体取决于数字是否小于(或等于)表中行数的一半
对于看起来像这样的SELECT
:
SELECT original_id,
duplicate_id,
CASE
WHEN rn <= (SELECT count(*) / 2
FROM elbat) THEN
'control'
ELSE
'treatment'
END tag
FROM (SELECT original_id,
duplicate_id,
row_number() OVER (ORDER BY random()) rn
FROM elbat) x;
如果您想要一个UPDATE
(我不确定),假设original_id
和duplicate_id
对是唯一的,则可能看起来像这样:
UPDATE elbat t
SET tag = CASE
WHEN rn <= (SELECT count(*) / 2
FROM elbat) THEN
'control'
ELSE
'treatment'
END
FROM (SELECT original_id,
duplicate_id,
row_number() OVER (ORDER BY random()) rn
FROM elbat) x
WHERE x.original_id = t.original_id
AND x.duplicate_id = t.duplicate_id;
db<>fiddle
(顺便说一句,小提琴上的SELECT
结果提供了一个很好的例子,如果优化程序更喜欢这样做,则返回的行的顺序可以与物理行的顺序完全不同。)
答案 2 :(得分:0)
我将使用窗口功能:
select t.*,
(case when seqnum <= cnt / 2
then 'treatment' else 'control
end) as tag
from (select t.*,
count(*) over () as cnt,
row_number() over (order by random() as seqnum
from t
) t;
实际上,随机是随机的。因此,您不需要计数。您可以改用模运算:
select t.*,
(case when row_number() over (order by random()) % 2 = 1
then 'treatment' else 'control'
end) as tag
from t;
答案 3 :(得分:0)
您可以使random()
使用以下公式生成值1或2:(random() + 1)::int
select t.*,
case (random() + 1)::int
when 1 then 'treatment'
else 'control'
end as tag
from t;
通常,(random() * (upper_limit - 1) + lower_limit)::int
会生成介于上限和下限(包括下限)之间的数字。如果上限为2,则可以删除乘法(因为它将是* 1
,它不会改变任何内容),但是如果您想例如生成四个随机值,您也可以使用它:
select t.*,
case (random() * 3 + 1)::int
when 1 then 'treatment'
when 2 then 'control'
when 3 then 'something'
else 'some other thing'
end as tag
from t;