Доброго времени суток!
В своём примере расчета числа повторных покупок, Андрей Свиридов приводит такой вот код:
//***Автор скрипта Свиридов Андрей
ДанныеПродаж:
LOAD НомерСчета,
ДатаСчета,
КодКлиента,
sum(Сумма)as Сумма
FROM
Продажи.qvd (qvd)
Group By НомерСчета, ДатаСчета, КодКлиента;
//Используем резидентную загрузку для формирования таблицы с уникальными идентификаторами клиентов
Temp:
LOAD Distinct
КодКлиента as CustomerID
Resident ДанныеПродаж;
//В переменнуя Score будет записываться дата последнего счета по каждому клиенту
Set Score = 0;
//Первый цикл FOR перебирает каждого клиента в таблеце Temp
FOR i=0 to NoOfRows('Temp')-1
//В переменную Customer записывается идентификатор клиента на каждой итерации цикла
Let Customer = Peek('CustomerID',$(i),'Temp');
//Таблица Temp1 содержит даты всех счетов по каждому клиенту
Temp1:
NoConcatenate
Load
ДатаСчета as ДатаСчета1
Resident ДанныеПродаж
Where КодКлиента = '$(Customer)';//Каждый клиент попадает в параметр отбора
//Второй цикл вычисляет самую позднюю дату счета
FOR l=0 to NoOfRows('Temp1')-1
IF(Peek('ДатаСчета1',$(l),'Temp1')>$(Score)) then
LET Score = Peek('ДатаСчета1',$(l),'Temp1');//Дата счета записывается в переменную Score
ENDIF
NEXT;
DROP Table Temp1;//больше данные этой таблицы не нужны, она заполнится следующим клиентом на следующей итерации
//Формируем из данных переменных таблицу
Temp2:
LOAD
'$(Customer)' as Client,
'$(Score)' as LastDate
AutoGenerate (1);
SET Score = 0;//Присваиваем переменной значение 0, необходимо для последующей работы цикла
NEXT;
//присоединяем дополнительное поле к таблице по ключу "КодКлиента"
Left Join (ДанныеПродаж)
LOAD
Client as КодКлиента,
LastDate as ДатаПоследнегоСчета
Resident Temp2;
//Избавляемся от лишних таблиц
DROP Table Temp;
DROP Table Temp2;
//Создаем новую таблицу используя резидентную загрузку
Temp3:
NoConcatenate
LOAD
НомерСчета,
ДатаСчета,
КодКлиента,
Сумма,
ДатаПоследнегоСчета,
If(ДатаПоследнегоСчета<MonthEnd(AddMonths(Today(),-2)),1,0) as ПотеряныйКлиент,//Клиенты не совершившие покупку более месяца
If(ДатаПоследнегоСчета<MonthEnd(AddMonths(Today(),-2)),Num(Month(ДатаПоследнегоСчета)),) as МесяцПотериКлиента,// Месяц в котором клиент совершал последнюю покупку
If(ДатаПоследнегоСчета>MonthEnd(AddMonths(Today(),-2)),Num(Month(ДатаСчета)),) as МесяцНаличияКлиента//Месяц в котором клмент остается клиентом
Resident ДанныеПродаж;
//Убираем таблицу
DROP Table ДанныеПродаж;
//Переименовывыем таблицу
RENAME Table Temp3 to ДанныеПродаж;
В данном цикле, вычисляем самую позднюю дату счета. Подскажите пожалуйста, как преобразовать цикл, что бы вычислить наоборот, первую дату покупки?
Спасибо!!
FOR l=0 to NoOfRows('Temp1')-1
IF(Peek('ДатаСчета1',$(l),'Temp1')>$(Score)) then
LET Score = Peek('ДатаСчета1',$(l),'Temp1');//Дата счета записывается в переменную Score
ENDIF
Привет, для чего использовать циклы?
Можно ведь сделать запрос на ID клиента и максимальную дату, т.о. мы получаем таблицу с ИД клиента и датой последней покупки. Т.е. получаем то же самое но намного быстрее и легче.
А Вы могли бы привести пример такого кода (запроса)?
LOAD
КодКлиента as CustomerID,
max(Дата) As ДатаКрайнейСделки
Resident ДанныеПродаж
group by КодКлиента;
Решение прекрасно подошло для задачи, большое спасибо.
Подскажите, а есть решение, если мне требуется найти минимальный и максимальный интервал в днях, между покупками для покупателя?
Сначала рассчитайте интервалы между покупками, затем рассчитывайте min, max.
Почитайте про previous & peek в хелпе (https://help.qlik.com/ru-RU/sense/June2017/Subsystems/Hub/Content/ChartFunctions/InterRecordFunctions/inter-record-functions-charts.htm)
Подскажите, а как выполнять расчет именно для конкретного клиента из таблицы, а не все по порядку?
Test1:
Load
КодКлиента,
Date(ДатаСчета) as ДатаСчета1,
Previous (Date(ДатаСчета)) as Previuos,
ДатаСчета - Previous (Date(ДатаСчета)) as Разница
Resident DistClients
Order by КодКлиента;
Если брать простое использование функции, вычитается все по порядку. Соответственно, каждое последнее вычитание, это последняя покупка одного клиента и первая другого.
Используйте проверку
load
...
if(КодКлиента=Previous(КодКлиента),
ДатаСчета - Previous (Date(ДатаСчета))) as Разница
...
Resident DistClients
Order by КодКлиента;
Test1:
Load
КодКлиента,
Date(ДатаСчета) as ДатаСчета1,
Previous(ДатаСчета) as Previous,
if(КодКлиента = Previous(КодКлиента), ДатаСчета-Previous(Date(ДатаСчета))) as Разница
Resident DistClients
Order by КодКлиента, ДатаСчета;
MinMax:
Load
КодКлиента,
If(КодКлиента, Min(Разница)) as МинДнейМеждЗак,
If(КодКлиента, Max(Разница)) as МаксДнейМеждЗак
Resident Test1
Group by КодКлиента;
Для нахождения минимальной и максимальной разницы, решил так же использовать if. Максимум считает для каждого покупателя, а минимум только для некоторых, избирательно. Подскажите, в чем ошибка?
Странно, что он вообще считает.
Зачем условия при группировке?
Просто вычисляйте минимум и максимум для клиента.
Сначала так и пробовал, не группировать. Но ругается на выражение.
MinMax << Test1
Ошибка скрипта: Invalid expression
Произошла следующая ошибка:
Invalid expression
Ошибка произошла здесь:
MinMax:
Load
КодКлиента,
If(КодКлиента, Min(Разница)) as МинДнейМеждЗак,
If(КодКлиента, Max(Разница)) as МаксДнейМеждЗак
Resident Test1
Произошла следующая ошибка:
Invalid expression
Ошибка произошла здесь:
?
Данные не загружены. Исправьте ошибку и повторите загрузку.
мин и макс работают только при группировке.
Load
КодКлиента,
Min(Разница) as МинДнейМеждЗак,
Max(Разница) as МаксДнейМеждЗак
Resident Test1
Group By КодКлиента;
Спасибо!!!
Возник еще вопрос по ходу.... Не могу сообразить, как мне объяснить функции autonumber, пронумеровать дату первой покупки для каждого покупателя. Есть код клиента, есть даты его покупок, есть дата первой покупки. Идея в том, что бы присвоить "1" первой его покупке, для определения количества новых покупателей за выбранную дату покупки. Либо пронумеровать каждую дату покупки (1,2,3.....), но так для каждого покупателя, начиная с "1".
НумерацияПокупок:
LOAD
Distinct (КодКлиента) as ClientID,
ДатаСчета as DateSale,
AutoNumber(ДатаСчета,[КодКлиента])
resident DistClients;
Вроде как разобрался)