#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 только для того, чтобы оставить окончательный запрос как можно более аккуратным.