使用另一个表作为随机值的集合随机更新一组值而不使用循环的方法?

问题描述 投票:4回答:2

我有一个包含一些值的列的表。我想用另一个表中的随机值替换所有现有值(但只有现有值 - 所以WHERE COL1 IS NOT NULL)。没有办法关联这两个表。每个随机值需要不同(嗯......除非它们是随机相同的,在这种情况下它很好)。

例如:

CREATE TABLE T1 (ID NUMBER(11,0), COL1 VARCHAR2(20));
CREATE TABLE T2 (COL2 VARCHAR2(20));

INSERT INTO T1 VALUES (1, NULL);
INSERT INTO T1 VALUES (54, NULL);
INSERT INTO T1 VALUES (941, 'Some text');
INSERT INTO T1 VALUES (251, NULL);
INSERT INTO T1 VALUES (352, 'Some other text');
INSERT INTO T1 VALUES (354, NULL);

INSERT INTO T2 VALUES ('Val1');
INSERT INTO T2 VALUES ('Val2');
INSERT INTO T2 VALUES ('Val3');
INSERT INTO T2 VALUES ('Val4');
INSERT INTO T2 VALUES ('Val5');
INSERT INTO T2 VALUES ('Val6');
INSERT INTO T2 VALUES ('Val7');

我尝试了一些东西,并搜索了这个网站的答案。我发现的答案似乎要求两个表之间存在某种相关性。很多例子都是针对SQL Server的。无论如何我已经尝试了一些,但我似乎无法获得MERGECROSS APPLY工作方法(我很欣赏这很可能是我的失败......)。

我现在唯一能解决的解决方案如下:

BEGIN
  FOR X IN (
    SELECT ID FROM T1 WHERE COL1 IS NOT NULL
  )
  LOOP
    UPDATE T1 SET COL1 = (
      SELECT COL2 FROM (
        SELECT COL2 FROM T2 ORDER BY SYS_GUID()
      ) WHERE ROWNUM = 1
    ) 
    WHERE T1.ID = X.ID;
  END LOOP;
END;
/

这产生了(期望的)结果:

SELECT * FROM T1;

ID           COL1
---------------------------
1            
54           
941          Val3
251          
352          Val7
354          

(每次运行循环时,COL1值都是随机的)。

......但我知道必须有基于集合的方式来实现这一点......对吗?

sql oracle
2个回答
2
投票

你可以用MERGE语句来做。

merge into t1
using ( select a1.id
               , a2.col2
        from ( select id
                      , row_number() over (order by dbms_random.value) rn
               from t1
               where col1 is not null ) a1
         join ( select col2
                      , row_number() over (order by dbms_random.value) rn
               from t2) a2
          on a1.rn = a2.rn
      ) q
on ( q.id = t1.id) 
when matched then
     update set t1.col1 = q.col2
/

USING查询有点不正统。有两个子查询,每个表一个,它以随机顺序生成分析row_number()(这比使用rownum更整洁。两个子查询连接在随机行数上,这给出了T1.ID和T2.COL_2的随机组合。在那之后,这是一个简单的合并。


1
投票

您可以创建名为GET_RANDOM_VALUE的FUNCTION

create or replace FUNCTION GET_RANDOM_VALUE 
RETURN VARCHAR2 AS
  sValue VARCHAR2(100) := '?';
BEGIN

  select col2 INTO sValue 
    from t2 
    order by dbms_random.value
    fetch first 1 rows only;

  RETURN sValue;
END GET_RANDOM_VALUE;

并且UPDATE命令可以

UPDATE t1
  SET col1 = GET_RANDOM_VALUE()
  WHERE col1 IS NOT NULL;

通常,我避免在函数中使用SELECT,但在这种情况下,我发现这个解决方案更易读,更容易理解。

© www.soinside.com 2019 - 2024. All rights reserved.