Способ случайного обновления набора значений с использованием другой таблицы в качестве коллекции случайных значений без использования цикла? - PullRequest
4 голосов
/ 04 апреля 2019

У меня есть таблица со столбцом, который содержит некоторые значения.Я хочу заменить все существующие значения случайными значениями из другой таблицы (но только существующие - так что 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.В любом случае я попробовал несколько, но я не могу получить подход MERGE или CROSS 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 оба являются случайными каждый раз, когда я запускаюцикл).

... Но я знаю, что должен быть основанным на множестве способом достижения этого ... верно?

Ответы [ 2 ]

2 голосов
/ 04 апреля 2019

Вы можете сделать это с помощью оператора 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. После этого это прямое MERGE.

1 голос
/ 04 апреля 2019

Вы можете создать ФУНКЦИЮ с именем GET_RANDOM_VALUE

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 в функции, но в этом случае я обнаружил,это решение более читаемое и более простое для понимания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...