0

假设我有一张桌子:

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中重复数字是不好的。例如,:

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 上。这对我来说真是头疼。提前致谢!

4

3 回答 3

1

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

select hh, slot, row_number() over (partition by hh order by random()) as rn
from t;

较大的值范围更具挑战性。下面计算一个表(称为randoms),其中包含相同范围内的数字和随机位置。然后它slot用于索引位置并从表中提取随机数randoms

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 足够接近以具有匹配的语法。

于 2013-07-31T01:40:55.417 回答
0

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

  1. 初始化一个计数器 CNT=1
  2. 创建一个表,以便您从每个组中随机抽取 1 行和一个空 RN 计数,例如 C_NULL_RN。
  3. 每行的概率为 C_NULL_RN/(10-CNT+1),将 CNT 指定为 RN
  4. 增加 CNT 并转到步骤 2
于 2013-07-31T01:38:24.820 回答
0

好吧,我找不到一个巧妙的解决方案,所以我做了一个 hack:

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

这是它的样子。懒得匿名了,所以名字和我原来的帖子有点不同:

/* 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
;
于 2013-08-05T20:02:05.563 回答