在Oracle SQL表中添加列,该列是来自另一列/表

时间:2018-03-30 20:26:04

标签: sql oracle random sample

我在SQL中有一个预先存在的表(MYORIGTABLE),我想添加一个列,它是来自另一个表(RANDNUM10)中的列的随机样本。另一张表是我预先确定的随机数的1列样本,并且想从中抽样;列名是RANDVAL。我尝试了以下

select (select randval from (SELECT randval FROM RANDNUM10 ORDER BY dbms_random.value) where rownum=1) as mynum from MYORIGTABLE

但不幸的是,这只是给了我相同的随机数,这是从RANDNUM10中采样的整个MYORIGTABLE重复的。如何进行采样以使MYORIGTABLE的每一行都获得一个新生成的样本?

谢谢, 科

3 个答案:

答案 0 :(得分:1)

这是您的查询:

select (select randval
        from (SELECT randval 
              FROM  RANDNUM10
              ORDER BY dbms_random.value
             ) 
        where rownum = 1
      ) as mynum
from MYORIGTABLE;

数据库优化器的一个常见问题 - 在这种情况下 - 它优化了对子查询的多次调用。它最终用一个调用替换子查询。

解决此问题的一种方法是使用相关子查询。为此,我建议删除一级嵌套:

select (select max(randval) keep (dense_rank first order by dbms_rnadom.value)
        from randnum10
        where myorigtable.id is not null -- or whatever
      ) as mynum
from MYORIGTABLE;

我认为这样可以工作,因此子查询被调用了10次,但可能需要更复杂的关联子句。

答案 1 :(得分:0)

也许是这样的事情?

测试用例:

SQL> create table myorigtable (id number);

Table created.

SQL> create table randnum10 (randval number);

Table created.

SQL> insert into myorigtable select level from dual connect by level <= 10;

10 rows created.

SQL> insert into randnum10 select round(dbms_random.value(1, 100)) from dual connect by level <= 10;

10 rows created.

SQL> alter table myorigtable add randval number;

Table altered.

更新

SQL> update myorigtable m set
  2    m.randval = (select x.randval
  3                 from (select randval, row_number() over (order by randval) rn
  4                       from randnum10
  5                      ) x
  6                 where x.rn = m.id
  7                );

10 rows updated.

SQL> select * from myorigtable;

        ID    RANDVAL
---------- ----------
         1          5
         2         18
         3         29
         4         31
         5         31
         6         62
         7         66
         8         87
         9         94
        10         98

10 rows selected.

SQL>

答案 2 :(得分:0)

这是一种方法。我假设您的RANDNUM10表有很多行(比MYORIGTABLE更多的行),您想要无需替换的随机数采样(从RANDNUM10中选择DISTINCT随机值) - 因此随机数table有足够的行 - 至少与MYORIGTABLE一样多 - 并且您需要将列添加到SELECT查询的结果集中,而不是添加到存储的表中。 (如果需要将结果存储在附加列中,则必须首先添加该列(如果该列尚不存在),并在SELECT语句中使用下面的UPDATE查询。)

策略很简单:将任意行号与较小的表相关联(值为1,2,...,N,其中N为行数),并将随机行号与随机数表中的行相关联。两者都可以使用ROW_NUMBER()...完成 - 第一个可以按NULL排序,因为我们需要的所有随机性都来自其他表的行号。然后在行号上加入两个表,从而添加到两个表中。

为了说明,我创建了MYORIGTABLE作为SCOTT.EMP的副本,只从该表中选择了几列。以下是查询的外观,以及使用MYORIGTABLE的输出。

<强>设置

create table myorigtable as select empno, ename, job, deptno from scott.emp;

create table randnum10 ( randval ) as
  select dbms_random.value() from dual connect by level <= 1000;

查询和输出

select a.empno, a.ename, a.job, a.deptno, b.randval
from   (
         select empno, ename, job, deptno, row_number() over (order by null) as rn
         from   myorigtable
       ) a
       inner join
       (
         select randval, row_number() over (order by dbms_random.value()) as rn
         from   randnum10
       ) b
       on a.rn = b.rn
;

EMPNO  ENAME       JOB        DEPTNO     RANDVAL
-----  ----------  --------- -------  ----------
 7369  SMITH       CLERK          20  .991998901
 7499  ALLEN       SALESMAN       30  .448133242
 7521  WARD        SALESMAN       30  .136242235
 7566  JONES       MANAGER        20  .443347421
 7654  MARTIN      SALESMAN       30  .836931008
 7698  BLAKE       MANAGER        30  .361437867
 7782  CLARK       MANAGER        10  .433786615
 7788  SCOTT       ANALYST        20  .285173363
 7839  KING        PRESIDENT      10  .063840361
 7844  TURNER      SALESMAN       30  .825888729
 7876  ADAMS       CLERK          20  .818415041
 7900  JAMES       CLERK          30  .150180080
 7902  FORD        ANALYST        20  .442389099
 7934  MILLER      CLERK          10  .086995415