首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >随机分表(postgreSQL) 50/50

随机分表(postgreSQL) 50/50
EN

Stack Overflow用户
提问于 2018-09-05 07:42:15
回答 4查看 1.2K关注 0票数 0

我在postgresql中有一个包含两列的表:原始id和复制id。

示例数据:

代码语言:javascript
复制
original_id   duplicate_id  
     1             1
     2             2
     3             3
     4             4
     5             5
     6             6

我想以50/50的比例随机拆分这张表,这样我就可以在每个表中放置一个特定的标签

示例数据:

代码语言:javascript
复制
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 (如果行数是奇数,则最接近于50)

EN

回答 4

Stack Overflow用户

发布于 2018-09-05 08:17:10

您可以使用以下查询以随机顺序选择一半的行:

代码语言:javascript
复制
select *
from my_table
order by random()
limit (select count(*)/ 2 from my_table)

使用它来标记行:

代码语言:javascript
复制
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;

Working example in rextester.

票数 0
EN

Stack Overflow用户

发布于 2018-09-05 08:19:07

您可以使用rownumber() OVER (ORDER BY random())为每条记录分配一个随机数。然后在CASE中使用它来分配标记'control''treatment',这取决于数字是否小于(或等于)表中行计数的一半。

对于如下所示的SELECT

代码语言:javascript
复制
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_idduplicate_id是唯一的,这可能看起来像这样:

代码语言:javascript
复制
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结果给出了一个很好的例子,返回的行的顺序可以与物理顺序完全不同,如果优化器更喜欢这样的话。)

票数 0
EN

Stack Overflow用户

发布于 2018-09-05 11:56:17

我会使用窗口函数:

代码语言:javascript
复制
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;

实际上,随机就是随机的。所以,你不需要计数。您可以改用模算法:

代码语言:javascript
复制
select t.*,
       (case when row_number() over (order by random()) % 2 = 1
             then 'treatment' else 'control'
        end) as tag
from t;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52175254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档