Частичная агрегация - PullRequest
1 голос
/ 16 января 2020

Примечание. Несмотря на то, что в настоящее время я фокусируюсь на t sql, это вполне может быть более общий вопрос sql.

Рассмотрим следующий пример запроса «правильный, но также псевдокод»:

select 
    desiredKeyCols,
    case count(distinct productID) 
        when 0 then '0'
        when 1 then '1'
        else '2+'
    end as [Product Count Classification]
from orders
group by desiredKeyCols

Поле [Классификация количества продуктов] будет возвращаться для каждого desiredKeyCols, 0, если нет связанных productID s, 1 для 1 и 2+ для любого более высокого числа. Однако count(distinct productID) не остановит свои вычисления, как только достигнет 2. Он с радостью продолжит бесконечность, а затем другая операция вычислит случай.

Я видел, как одна и та же вещь возникала несколько раз.

Есть ли более эффективный способ реализовать это? Если нам нужен только класс 0/1 +, ответ таков: полу соединение (в / существует). Но как насчет произвольного числа диапазонов?

1 Ответ

1 голос
/ 16 января 2020

Там, наверное, мало что можно сделать. Но есть два альтернативных способа express запроса, которые могут иметь лучшую производительность.

Если у вас есть индекс для «(требуемый ключ, productid)» и, возможно, «(требуемый ключ, производственный des c)» , вы можете попробовать:

select desiredKeycols,
       (case distinct_cnt . . . )
from (select o.*,
             (dense_rank() over (partition by desiredKeycols order by productid) +
              dense_rank() over (partition by desiredKeycols order by productid desc)
             ) as distinct_cnt
      from orders o
     ) o
group by desiredKeycols;

Это не останавливается на "3", но возможно, что он будет оптимизировать лучше, чем count(distinct).

На самом деле, небольшая альтернатива будет использовать только один индекс:

select desiredKeycols,
       (case cnt . . . )
from (select o.desiredKeycols, count(*) as cnt
      from orders o
      group by desiredKeycols, productid
     ) o
group by desiredKeycols;

В некоторых базах данных это значительно быстрее, чем count(distinct). Тем не менее, я думаю, что SQL Сервер имеет лучший оптимизатор, так что это может не быть большой победой.

...