我在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的每一行都获得一个新生成的样本?
谢谢, 科
答案 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