Неофициальный форум пользователей Qlik Sense & Qlikview

Для разработчиков => Вопросы по Qlik Sense & QlikView => Тема начата: Oleg от 11 марта 2017, 10:16:21

Название: Определение даты первого счета Клиента
Отправлено: Oleg от 11 марта 2017, 10:16:21
Казалось бы, воспользуйся ты функцией min(Дата счета) и прекращай заниматься ерундой в субботу вечером. Но не все так просто..
Есть еще правило: первым счетом Клиента считается такой счет, дата выставления которого больше даты выставления предыдущего счета на этого Клиента на 365 дней и более.
Пожалуй, это можно было бы реализовать на стадии скрипта загрузки, но в силу того что Счета связаны с Клиентами через несколько таблиц и наличия еще одного правила "на вырост"(в конце), я этого не делаю..
Пытаюсь выкрутить это через анализ множество, но все тщетно.
Пример не работающей формулы, которая по моей задумке должна была бы сработать:
max(
aggr({1<Номер счета = {"=rangesum(Дата счета,-below(Дата счета))>365"}>}
Дата счета,
Клиент, Дата счета(Numeric,Descending)))
)

Ситуацию еще усугубляет наличие 2х типов счетов:разовый(за одну услугу) и групповой(за несколько услуг), которые лежат в разных таблицах и конкатенировать которые пока тоже весьма затруднительно.
Но с этим я как нибудь разберусь уж..

Правило на вырост: первым счетом Клиента по Продукту считается такой счет, дата выставления которого больше даты выставления предыдущего счета на этого Клиента по этому же продукту на 365 дней.
По идее должно выглядеть как-то так:
max(
aggr({1<Номер счета = {"=rangesum(Дата счета,-below(Дата счета))>365"}>}
Дата счета,
Клиент, Продукт, Дата счета(Numeric,Descending)))
)

Совсем уже извелся с этой задачей :(
Название: Re: Определение даты первого счета Клиента
Отправлено: admin от 11 марта 2017, 10:41:43
Привет.

Мой совет - решить в скрипте. Слишком много вычислений в принципе, а еще и с проверкой на диапазон между датами...
Надо будет в едином реестре все счета отсортировать и расставить индексы согласно вашим установкам, причем индексы можно будет сделать разные за один запрос.
И на общий порядковый номер заказа по клиенту, и с периодами и еще с чем-то на будущее...

aggr() с множествами - отличные помощники, но не там где много записей или мало ресурсов.
Название: Re: Определение даты первого счета Клиента
Отправлено: millik от 13 марта 2017, 09:49:09
Цитата: admin от 11 марта  2017, 10:41:43  
aggr() с множествами - отличные помощники, но не там где много записей или мало ресурсов.
И даже там где ресурсов хватает. Агрегации и расчеты на лету очень сильно грузят проц. И нагрузка растет в геометрической прогрессии от увеличения объема обрабатываемых данных.
Название: Re: Определение даты первого счета Клиента
Отправлено: Oleg от 20 июня 2017, 09:13:58
Благодарю за советы!
Буду пробовать.
Долго я конечно отписываюсь. Только нашел время снова посетить форум.
Название: Re: Определение даты первого счета Клиента
Отправлено: millik от 23 июня 2017, 11:34:54
Я конечно на своих данных, но вот накидал такой вариант без расчета в скрипте.

Обычно когда нужно строить агрегации, особенно сложные, я сначала строю таблицу, которую потом хочу запихнуть в Aggr(). В ней шаг за шагом развиваю меру, пока не получу нужное выражение. Потому что, если пытаться "взять" с наскока, то получается фигня + можно отловить на каком этапе происходит ошибка.

И так имеем две таблицы. Первая - рабочая, вторая уже с агрегацией.
Как вариант:
(https://qliksense-forum.ru/qvf/proxy.php?request=http%3A%2F%2Fi93.fastpic.ru%2Fbig%2F2017%2F0623%2F68%2F3218446c85b703efeee662aa9026a268.png&hash=8852c4ee37cc9c213a3dba906e23a94279590b93)

В первой таблице:
1) Карта - измерение
2) Дата - измерение
3) Дата - уже мера, но просто без обработки
4) Дней с прошлой покупки - высчитываем шаг дат прошлой меры.
[Дата]-Above([Дата])
5) Дней > 60 - а вот тут уже смотрим где шаг больше допустимого. Проверяем на Null, он будет вообще при первой покупке и второе условие уже на количество дней. Если условие выполнено, то записываем дату, если нет то Null. Обязательно Null, а не 0 или "". Т.к. 0 и "" - значения и они участвует во всяких Min/Max/Avg, а Null игнорится)
If(IsNull([Дата]-Above([Дата])) Or ([Дата]-Above([Дата]))>60,[Дата],Null())

Ну а во второй таблице уже играемся с агрегацией и придумываем что хотим получить на выходе. Например:
1) Карта - измерение
2) Мин дата (сама первая попкупка)
Date(Min(Aggr(IsNull([Дата]-Above([Дата])) Or ([Дата]-Above([Дата]))>60,[Дата],Null()),[Карта],[Дата])))
3) Макс дата (последнее возвращение клиента)
Date(Max(Aggr(IsNull([Дата]-Above([Дата])) Or ([Дата]-Above([Дата]))>60,[Дата],Null()),[Карта],[Дата])))
4) Кол возвращений клиента
Count(Aggr(IsNull([Дата]-Above([Дата])) Or ([Дата]-Above([Дата]))>60,[Дата],Null()),[Карта],[Дата]))

Название: Re: Определение даты первого счета Клиента
Отправлено: millik от 23 июня 2017, 11:37:23
И это пока не очень сложные агрегации, должно всё нормально считать.

У меня вот в оборачиваемости Aggr() в Aggr() с Aggr() в Set Analysis. И ничего считает понемногу. Ограничил только условия для расчета таблиц, чтобы народ не выбирал все периоды по всем товарам, ато тогда точно всё виснет.
Название: Re: Определение даты первого счета Клиента
Отправлено: Oleg от 27 июня 2017, 12:42:39
Цитата: millik от 23 июня  2017, 11:37:23  
И это пока не очень сложные агрегации, должно всё нормально считать.

У меня вот в оборачиваемости Aggr() в Aggr() с Aggr() в Set Analysis. И ничего считает понемногу. Ограничил только условия для расчета таблиц, чтобы народ не выбирал все периоды по всем товарам, ато тогда точно всё виснет.

Благодарю за столь детальное описание!
Проблема в том, что я точно таким же подходом пытался это реализовать. Но выдавало какую-то ерунду на определенным точках данных, не верно считало количество дней уже на стадии формирования обычной таблицы, без участия aggr(). Попробую проиллюстрировать пример в обозримом будущем.

Мое почтение :)