Случайное помечение записей в таблице Oracle

#sql #oracle

#sql #Oracle

Вопрос:

Учитывая таблицу идентификаторов в базе данных Oracle, каков наилучший метод случайного помечения (x) процентов из них? В приведенном ниже примере я случайным образом помечаю 20% всех записей.

 ID  ELIG
1   0
2   0
3   0
4   1
5   0
  

Мой текущий подход, показанный ниже, работает нормально, но мне интересно, есть ли более эффективный способ сделать это?

 WITH DAT
     AS (    SELECT LEVEL AS "ID"
               FROM DUAL
         CONNECT BY LEVEL <= 5),
     TICKETS
     AS (SELECT "ID", 1 AS "ELIG"
           FROM (  SELECT *
                     FROM DAT
                 ORDER BY DBMS_RANDOM.VALUE ())
          WHERE ROWNUM <= (SELECT ROUND (COUNT (*) / 5, 0) FROM DAT)),
     RAFFLE
     AS (SELECT "ID", 0 AS "ELIG"
           FROM DAT
          WHERE "ID" NOT IN (SELECT "ID"
                               FROM TICKETS)
         UNION
         SELECT * FROM TICKETS)
SELECT *
  FROM RAFFLE;
  

Ответ №1:

Здесь вы могли бы использовать ROW_NUMBER подход:

 WITH cte AS (
    SELECT t.*, ROW_NUMBER() OVER (ORDER BY dbms_random.value) rn,
                COUNT(*) OVER () cnt
    FROM yourTable t
)

SELECT t.*,
    CASE WHEN rn / cnt <= 0.2 THEN 'FLAG' END AS flag  -- 0.2 to flag 20%
FROM cte t
ORDER BY ID;
  

ДЕМОНСТРАЦИЯ

Пример вывода для одного запуска приведенного выше запроса:

снимок экрана

Обратите внимание, что помечена одна из пяти записей, что составляет 20%.

Комментарии:

1. Отлично работает. Большое спасибо! Есть ли что-то неправильное в том, чтобы поместить COUNT(*) ПОВЕРХ() в последней части запроса, сразу после оператора деления, вместо того, чтобы сохранять его в виде столбца в cte?

2. @DJC Нет, не существует, и вы можете это сделать. Я включил это в CTE только для того, чтобы оставить окончательный запрос как можно более аккуратным.