Создать таблицу из цикла вывода Oracle SQL - PullRequest
0 голосов
/ 27 сентября 2018

Мне нужно взять случайную выборку из таблицы ~ 5 миллионов наблюдений, основанной на 175 демографических вариантах.Демографическая таблица выглядит примерно так:

1 40 4%
2 30 3%
3 30 3%
- -
174 2 .02%
175 1 .01%

По сути, мне нужен тот же самый демографический анализ, случайно выбранный из таблицы строк 5M.Для каждой демографии мне нужна выборка из той же самой таблицы из более крупной таблицы, но с 5-кратным числом наблюдений (пример: для демографической 1 я хочу случайную выборку из 200).

SELECT  *
FROM    (
        SELECT  *
        FROM    my_table
        ORDER BY
                dbms_random.value
        )
WHERE rownum <= 100;

Я использовал этот синтаксис раньше, чтобы получить случайную выборку, но есть ли способ изменить это как цикл и заменить имена переменных из существующих таблиц?Я попытаюсь инкапсулировать нужную мне логику в псевдокод:

for (each demographic_COLUMN in TABLE1) 
    select random(5*num_obs_COLUMN in TABLE1) from ID_COLUMN in TABLE2
/*somehow join the results of each step in the loop into one giant column of IDs */

1 Ответ

0 голосов
/ 27 сентября 2018

Вы можете присоединиться к своим таблицам (при условии, что демографическое значение 1-175 существует в обеих или есть эквивалентный столбец для объединения), что-то вроде:

select id
from (
  select d.demographic, d.percentage, t.id,
    row_number() over (partition by d.demographic order by dbms_random.value) as rn
  from demographics d
  join my_table t on t.demographic = d.demographic
)
where rn <= 5 * percentage

Каждая строка в главной таблицедан случайный псевдоряд-номер в пределах своей демографии (через аналитику row_number()).Внешний запрос затем использует соответствующий процент, чтобы выбрать, сколько из этих случайно упорядоченных строк для каждого демографического объекта нужно вернуть.

Я не уверен, что понял, как вы на самом деле выбираете, сколько из каждоговы хотите, так что, вероятно, необходимо скорректировать.

Демонстрация с меньшей выборкой в ​​CTE и соответствием меньшему условию соответствия:

-- CTEs for sample data
with my_table (id, demographic) as (
  select level, mod(level, 175) + 1 from dual connect by level <= 175000
),
demographics (demographic, percentage, str) as (
            select 1, 40, '4%' from dual
  union all select 2, 30, '3%' from dual
  union all select 3, 30, '3%' from dual
  -- ...
  union all select 174, 2, '.02%' from dual
  union all select 175, 1, '.01%' from dual
)
-- actual query
select demographic, percentage, id, rn
from (
  select d.demographic, d.percentage, t.id,
    row_number() over (partition by d.demographic order by dbms_random.value) as rn
  from demographics d
  join my_table t on t.demographic = d.demographic
)
where rn <= 5 * percentage;

DEMOGRAPHIC PERCENTAGE         ID         RN
----------- ---------- ---------- ----------
          1         40      94150          1
          1         40      36925          2
          1         40     154000          3
          1         40      82425          4
...
          1         40     154350        199
          1         40     126175        200
          2         30      36051          1
          2         30       1051          2
          2         30     100451          3
          2         30      18026        149
          2         30     151726        150
          3         30     125302          1
          3         30     152252          2
          3         30     114452          3
...
          3         30     104652        149
          3         30      70527        150
        174          2      35698          1
        174          2      67548          2
        174          2     114798          3
...
        174          2      70698          9
        174          2      30973         10
        175          1     139649          1
        175          1     156974          2
        175          1     145774          3
        175          1      97124          4
        175          1      40074          5

(вам нужен только идентификатор, но явключаю другие столбцы для контекста);или более кратко:

with my_table (id, demographic) as (
  select level, mod(level, 175) + 1 from dual connect by level <= 175000
),
demographics (demographic, percentage, str) as (
            select 1, 40, '4%' from dual
  union all select 2, 30, '3%' from dual
  union all select 3, 30, '3%' from dual
  -- ...
  union all select 174, 2, '.02%' from dual
  union all select 175, 1, '.01%' from dual
)
select demographic, percentage, count(id) as ids, min(id) as min_id, max(id) as max_id
from (
  select d.demographic, d.percentage, t.id,
    row_number() over (partition by d.demographic order by dbms_random.value) as rn
  from demographics d
  join my_table t on t.demographic = d.demographic
)
where rn <= 5 * percentage
group by demographic, percentage
order by demographic;

DEMOGRAPHIC PERCENTAGE        IDS     MIN_ID     MAX_ID
----------- ---------- ---------- ---------- ----------
          1         40        200        175     174825
          2         30        150          1     174126
          3         30        150       2452     174477
        174          2         10      23448     146648
        175          1          5      19074     118649

дБ <> скрипка

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