Oracle SQL: как выбрать N записей для каждой «группы» / «кластера» - PullRequest
4 голосов
/ 14 июля 2011

У меня есть таблица big_table , с 4 миллионами записей, они сгруппированы в 40 групп через столбец с именем " process_type_cod ".Список значений, которые может принимать этот столбец, находится во второй таблице.Давайте назовем это small_table .

Итак, у нас есть big_table с NOT NULL FK с именем process_type_cod, который указывает на small_table (предположим, что имя столбца одинаково в обеих таблицах).

Я хочу N записей (т.е. 10) из big_table, для каждой записи small_table.

Т.е. 10 записей из big_table, относящихся к первой записи small_table UNION 10 записей, отличных от big_table, относящихся ко второй записи small table, и т. Д.

Можно ли получить с помощьюодна функция SQL?

1 Ответ

10 голосов
/ 14 июля 2011

Я рекомендую аналитическую функцию, такую ​​как rank () или row_number ().Вы можете сделать это с помощью жестко закодированных союзов, но аналитическая функция сделает всю тяжелую работу за вас.

select *
from 
(
    select
      bt.col_a,
      bt.col_b,
      bt.process_type_cod,
      row_number() over ( partition by process_type_cod order by col_a nulls last ) rank
    from small_table st
    inner join big_table bt
      on st.process_type_cod = bt.process_type_cod
)
where rank < 11
;

Возможно, вам даже не понадобится это объединение, так как в big_table есть все типы, которые вам нужны.В этом случае просто измените условие from на использование big_table и отбросьте объединение.

Для этого выполняется запрос, а затем сортировка записей с использованием оператора order by в операторе partition.Для данной группы (здесь мы сгруппированы по col_a) числовой номер строки (т.е. 1, 2, 3, 4, 5, n + 1 ...) применяется к каждой записи последовательно.Во внешнем предложении where просто отфильтруйте записи по номеру ниже N.

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