Страницы: 1
RSS
DAX или PQ: посчитать кол-во артикулов, по которым произошло изменение цен с предыдущим днем, подорожание и удешевление товаров
 
Доброго дня всем.
У меня есть ежедневный прайс, мне нужно понять, сколько артикулов с каждым днем дешевеет или дорожает? Хочу решить данную задачу с помощью DAX, т.к. его хоть немного понимаю, но можно и в PQ (я то в нем только мышкоклацаю). Во вложении есть мои расчеты того, сколько артикулов пришло и ушло каждый день, но вот посчитать изменение цен у меня не получается.
 
Доброе время суток.
Вариант для подражавших к текущему дню (для подешевевших аналогично) - лобовое решение.
Код
=
SUMX (
    SUMMARIZE ( 'прайс'; 'прайс'[бренд]; 'прайс'[артикул]; 'прайс'[дата] );
    VAR curDate = 'прайс'[дата]
    VAR prevPrice =
        CALCULATETABLE (
            'прайс';
            FILTER ( ALL ( 'календарь' ); 'календарь'[дата] < curDate );
            ALLEXCEPT ( 'прайс'; 'прайс'[бренд]; 'прайс'[артикул] )
        )
    VAR prevSum =
        SUMX ( TOPN ( 1; prevPrice; 'прайс'[дата]; DESC ); 'прайс'[цена] )
    VAR curSum =
        CALCULATE ( SUM ( 'прайс'[цена] ) )
    RETURN
        IF ( curSum > prevSum && NOT ( ISBLANK ( prevSum ) ); 1; BLANK () )
)
 
Андрей VG, большое спасибо за решение! Единственное не могу понять, как работает эта часть кода:
Код
SUMX ( TOPN ( 1; prevPrice; 'прайс'[дата]; DESC ); 'прайс'[цена] )
 
Цитата
Vladimir Chebykin написал:
как работает эта часть кода:
А для начала, давайте введём определения, куда без них?
Считаем, что в таблице "Прайс"  поля "Бренд", "Артикул", "Дата" однозначно определяют запись - это первичный ключ.
Считаем, что рост или падение цены определяется между ближайшими датами текущей и меньшей даты того же самого артикула бренда (если разница между датами одних и тех же бренда и артикула строго один день, то нужно использовать несколько другой подход). Естественно, если такая ближайшая по дате запись существует.
Из определений алгоритм.
Для текущей даты данного артикула бренда находим ближайшую по меньшим датам запись и сравниваем цены. Если текущая больше, то рост, если меньше то падение, иначе без изменений.
Код
=
SUMX (
    // Создаём строковый контекст по бренду, артикулу дате таблицы "Прайс"
    SUMMARIZE ( 'прайс'; 'прайс'[бренд]; 'прайс'[артикул]; 'прайс'[дата] );
    VAR curDate = 'прайс'[дата] // получаем текущую дату
    // получаем подтаблицу бренда и артикула, где даты меньше текущей
    VAR prevPrice =
        CALCULATETABLE (
            'прайс';
            FILTER ( ALL ( 'календарь' ); 'календарь'[дата] < curDate );
            ALLEXCEPT ( 'прайс'; 'прайс'[бренд]; 'прайс'[артикул] )
        )
    // TOPN ( 1; prevPrice; 'прайс'[дата]; DESC ) вернёт, в силу сортировки ближайшую по дате запись для данного артикула бренда
    // ну, а SUMX - только для того чтобы получить цену и ближайшей предшествующей записи
    VAR prevSum = 
        SUMX ( TOPN ( 1; prevPrice; 'прайс'[дата]; DESC ); 'прайс'[цена] )
// аналогично, используя SUM получаем цену на текущую дату, помним, что CALCULATE - в данном случае будет использовать строковый контекст для фильтрации
    VAR curSum =
        CALCULATE ( SUM ( 'прайс'[цена] ) )
    RETURN
        // ну и собственно, 1 если текущая больше и предшествующее данное существует
        IF ( curSum > prevSum && NOT ( ISBLANK ( prevSum ) ); 1; BLANK () )
)

Если строго с разницей в один день, то prevPrice просто находим по
Код
   VAR prevPrice =
        CALCULATETABLE (
            'прайс';
            FILTER ( ALL ( 'календарь' ); 'календарь'[дата] = (curDate - 1) );
            ALLEXCEPT ( 'прайс'; 'прайс'[бренд]; 'прайс'[артикул] )
        )
в этом случае TOPN уже не нужен - запись одна с силу исходного определения первичного ключа.
 
Ох, большое спасибо за такой развернутый ответ! Аплодирую стоя, как говорится! Теперь стало понятно, что к чему.
Страницы: 1
Наверх