Совокупное количество различных в Netezza

Я использую Netezza. Я работаю с маркетинговыми данными, особенно с купонами. Прямо сейчас я подсчитываю отдельных ежедневных купонов; ничего страшного. Тем не менее, я хотел бы получить количество различных искупителей на сегодняшний день. Обратите внимание, что это не просто сумма ежедневных выкупов, так как клиент может выкупать в разные дни, и, следовательно, сумма ежедневных выкупов может быть несколькими клиентами.

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

select redemption_date
      ,count(distinct(customer_id)) as day_redeemers
      ,count(distinct(customer_id)) over (partition by null rows unbounded preceding) as cml_redeemers
from coupon_history
group by 1
order by 1

Но Netezza жалуется: ОШИБКА [HY000] ОШИБКА: атрибут CUSTOMER_ID должен быть сгруппирован или использован в агрегатной функции.

... и поэтому я закрываю глаза, загадываю желание и выполняю следующее (обратите внимание на добавление в группу):

select redemption_date
      ,count(distinct(customer_id)) as day_redeemers
      ,count(distinct(customer_id)) over (partition by null rows unbounded preceding) as cml_redeemers
from coupon_history
group by 1,customer_id
order by 1

Netezza жалуется на следующее:

ERROR [HY000] ERROR:  DISTINCT aggregate not allowed in window with ORDER BY or frame specification

Эта ошибка наводит меня на мысль, что внутри Netezza заказывает customer_id для подсчета переходов и, таким образом, различий. Но это оставляет меня в растерянности относительно того, что я должен попробовать дальше. Я надеялся на что-то простое, но видимо сегодня не мой счастливый день.

Любые идеи о том, как заставить мой первоначальный запрос работать, или предложения по альтернативному подходу?

Спасибо!


person Chris    schedule 12.12.2014    source источник


Ответы (1)


Вы всегда можете прибегнуть к грубой силе, то есть к коррелированному подзапросу:

select redemption_date,
       count(distinct(customer_id)) as day_redeemers,
       (select count(distinct ch2.customer_id)
        from coupon_history ch2
        where ch2.redemption_date <= ch.redemption_date
       ) as cml_redeemers
from coupon_history ch
group by 1
order by 1;

Конечно, производительность будет не такой хорошей.

РЕДАКТИРОВАТЬ:

Другой способ приблизиться к этому — получить первую дату погашения для каждого клиента, а затем просто использовать кумулятивные суммы:

select minrd,
       sum(count(*)) over (order by minrd) as cml_redeemers
from (select ch.customer_id, min(redemption_date) as minrd
      from coupon_history ch
      group by ch.customer_id
     ) ch
group by minrd;
person Gordon Linoff    schedule 12.12.2014
comment
Второй подход должен быть умным, потому что мне трудно его понять. Но похоже, что вы рассматриваете дату первого погашения клиентов как своего рода идентификатор этого клиента... и, поскольку у них может быть только одна минимальная дата, мы не дублируем последующие дни. Я действительно думаю, что вы имеете в виду sum(count(*)) over (order by minrd)... в противном случае вы просто получите номера строк. - person Chris; 12.12.2014
comment
@Крис. . . У вас совершенно правильное представление о втором подходе. И да, это должно быть sum(count(*)) (сейчас это исправлено). - person Gordon Linoff; 12.12.2014
comment
Прохладный. Это прекрасно работает! Что касается первого подхода, я всегда забываю о коррелированных подзапросах (особенно как об одном выбранном значении)... Я думаю, что это подсознательный защитный механизм. Тем не менее, я попробовал это, и, очевидно, Netezza не хочет участвовать в этом. Он жалуется: эта форма коррелированного запроса не поддерживается — рассмотрите возможность перезаписи. В любом случае, спасибо! - person Chris; 12.12.2014
comment
@Крис. . . Странно, что Netezza не поддерживает первую версию. Это стандартный SQL, и Postgres поддерживает синтаксис. Я удивлен. - person Gordon Linoff; 12.12.2014
comment
Ну... может быть, я сломал его. Мой запрос выше был упрощен, чтобы удалить некоторые файлы where. Запрос не будет хорошо вставляться в это маленькое поле, но он у меня есть на http://www.wepaste.com/hammondegger/, если вы хотите взглянуть (я поставил там два пробела, чтобы SO не сломался моя ссылка). - person Chris; 12.12.2014
comment
@Крис. . . Ваш запрос выглядит разумным; это, вероятно, ограничение Netezza. - person Gordon Linoff; 12.12.2014