首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在组中不重复的SQL随机数

在组中不重复的SQL随机数
EN

Stack Overflow用户
提问于 2013-07-31 01:28:49
回答 3查看 1.9K关注 0票数 0

假设我有一张桌子:

代码语言:javascript
运行
复制
HH  SLOT  RN
--------------
 1     1  null
 1     2  null
 1     3  null
--------------
 2     1  null
 2     2  null
 2     3  null

我想把RN设为介于1到10之间的随机数。这个数字可以在整个表中重复,但是在任何给定的HH中重复这个数字是不好的。例如:

代码语言:javascript
运行
复制
HH  SLOT  RN_GOOD  RN_BAD
--------------------------
 1     1        9       3
 1     2        4       8
 1     3        7       3  <--!!!
--------------------------
 2     1        2       1
 2     2        4       6
 2     3        9       4

这是在Netezza,如果它有任何不同。这对我来说是个大麻烦。提前感谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-08-05 20:02:05

嗯,我找不到一个好办法,所以我做了一个黑客:

  1. 创建了一个名为rand_inst的新整数字段。
  2. 为每个空槽分配一个随机数。
  3. rand_inst更新为这个家庭中该随机数的实例号。例如,如果我得到两个3,那么第二个3将rand_inst设置为2。
  4. 更新表,以便在rand_inst>1所在的任何地方分配不同的随机数。
  5. 重复分配和更新,直到我们收敛到一个解决方案。

看上去是这样的。太懒散了,所以名字和我原来的帖子有点不同:

代码语言:javascript
运行
复制
/* Iterative hack to fill 6 slots with a random number between 1 and 13.
   A random number *must not* repeat within a household_id.
*/
update c3_lalfinal a
set a.rand_inst = b.rnum
from (
    select household_id
          ,slot_nbr
          ,row_number() over (partition by household_id,rnd order by null) as rnum
    from c3_lalfinal
) b
where a.household_id = b.household_id
  and a.slot_nbr = b.slot_nbr
;

update c3_lalfinal
set rnd = CAST(0.5 + random() * (13-1+1) as INT)
where rand_inst>1
;

/* Repeat until this query returns 0: */
select count(*) from (
  select household_id from c3_lalfinal group by 1 having count(distinct(rnd)) <> 6
) x
;
票数 0
EN

Stack Overflow用户

发布于 2013-07-31 01:40:55

要在1和hh中的行数之间获得一个随机数,可以使用:

代码语言:javascript
运行
复制
select hh, slot, row_number() over (partition by hh order by random()) as rn
from t;

更大范围的值更具有挑战性。下面的表(称为randoms)具有相同范围内的数字和随机位置。然后使用slot索引位置,并从randoms表中提取随机数:

代码语言:javascript
运行
复制
with nums as (
      select 1 as n union all select 2 union all select 3 union all select 4 union all select 5 union all
      select 6 union all select 7 union all select 8 union all select 9
     ),
     randoms as (
      select n, row_number() over (order by random()) as pos
      from nums
     )
select t.hh, t.slot, hnum.n
from (select hh, randoms.n, randoms.pos
      from (select distinct hh
            from t
           ) t cross join
           randoms
     ) hnum join
     t
     on t.hh = hnum.hh and
        t.slot = hnum.pos;

这里是一个在Postgres中演示这一点的SQLFiddle,我认为它与Netezza非常接近,具有匹配的语法。

票数 1
EN

Stack Overflow用户

发布于 2013-07-31 01:38:24

我不是SQL方面的专家,但可能会这样做:

  1. 初始化计数器CNT=1
  2. 创建一个表,以便从每个组中随机抽取1行并计数为null RN,比如C_NULL_RN。
  3. 对于每一行的概率C_NULL_ RN /(10- CNT +1),将CNT赋值为RN
  4. 增加CNT并转到步骤2
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17960138

复制
相关文章

相似问题

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