Как использовать функцию DAX ParallelPeriod - PullRequest
5 голосов
/ 29 марта 2012

Функция ParaellePeriod позволяет сравнивать значения между моментами времени (как продажи сравниваются с прошлым годом). Я делаю что-то не так в своем использовании, но понятия не имею, что это за вещь .

Настройка

Я создал простой простой запрос источника PowerPivot SQL Server 2008+ и назвал его «Источник». Запрос генерирует 168 строк: 6 идентификаторов (100-600) и 28 дат (первое число месяца с января 2010 г. по апрель 2012 г.), все перекрестно применяются вместе.

; WITH SRC (groupKey, eventDate, value) AS
(
    SELECT G.groupKey, D.eventDate, CAST(rand(G.groupKey * year(D.eventDate) * month(D.eventDate)) * 100 AS int)
    FROM
    (
        SELECT 100
        UNION ALL SELECT 200
        UNION ALL SELECT 300
        UNION ALL SELECT 400
        UNION ALL SELECT 500
        UNION ALL SELECT 600
    ) G (groupKey)
    CROSS APPLY
    (
                  SELECT CAST('2010-01-01' AS date)
        UNION ALL SELECT CAST('2010-02-01' AS date)
        UNION ALL SELECT CAST('2010-03-01' AS date)
        UNION ALL SELECT CAST('2010-04-01' AS date)
        UNION ALL SELECT CAST('2010-05-01' AS date)
        UNION ALL SELECT CAST('2010-06-01' AS date)
        UNION ALL SELECT CAST('2010-07-01' AS date)
        UNION ALL SELECT CAST('2010-08-01' AS date)
        UNION ALL SELECT CAST('2010-09-01' AS date)
        UNION ALL SELECT CAST('2010-10-01' AS date)
        UNION ALL SELECT CAST('2010-11-01' AS date)
        UNION ALL SELECT CAST('2010-12-01' AS date)
        UNION ALL SELECT CAST('2011-01-01' AS date)
        UNION ALL SELECT CAST('2011-02-01' AS date)
        UNION ALL SELECT CAST('2011-03-01' AS date)
        UNION ALL SELECT CAST('2011-04-01' AS date)
        UNION ALL SELECT CAST('2011-05-01' AS date)
        UNION ALL SELECT CAST('2011-06-01' AS date)
        UNION ALL SELECT CAST('2011-07-01' AS date)
        UNION ALL SELECT CAST('2011-08-01' AS date)
        UNION ALL SELECT CAST('2011-09-01' AS date)
        UNION ALL SELECT CAST('2011-10-01' AS date)
        UNION ALL SELECT CAST('2011-11-01' AS date)
        UNION ALL SELECT CAST('2011-12-01' AS date)
        UNION ALL SELECT CAST('2012-01-01' AS date)
        UNION ALL SELECT CAST('2012-02-01' AS date)
        UNION ALL SELECT CAST('2012-03-01' AS date)
        UNION ALL SELECT CAST('2012-04-01' AS date)
    ) D (eventDate)
)
SELECT
    *
FROM
    SRC;

Я добавил производный столбец в PowerPivot, используя формулу, которую я поднял из MSDN

=CALCULATE(SUM(Source[value]), PARALLELPERIOD(Source[eventDate], -1, year))

Ошибки не отображаются, но расчетные данные отсутствуют. Я пробовал разные интервалы (-1, +1) и периоды (год, месяц), но безрезультатно.

Единственное, что я мог наблюдать, отличаясь между моей демонстрацией и MSDN, было то, что у них было определенное измерение для даты. Достаточно легко исправить, поэтому я создал запрос Dates со следующим. Этот запрос создает строку для всех дней между 2010-01-01 и 2012-06-01 (1096 строк)

DECLARE
    @start int = 20100101
,   @stop int = 20120601;

WITH L0 AS
(
    SELECT
        0 AS C
    UNION ALL
    SELECT
        0
)
, L1 AS
(
    SELECT
        0 AS c
    FROM
        L0 AS A
        CROSS JOIN L0 AS B
)
, L2 AS
(
    SELECT
        0 AS c
    FROM
        L1 AS A
        CROSS JOIN L1 AS B
)
, L3 AS
(
    SELECT
        0 AS c
    FROM
        L2 AS A
        CROSS JOIN L2 AS B
)
, L4 AS
(
    SELECT
        0 AS c
    FROM
        L3 AS A
        CROSS JOIN L3 AS B
)
, L5 AS
(
    SELECT
        0 AS c
    FROM
        L4 AS A
        CROSS JOIN L4 AS B
)
, NUMS AS
(
    SELECT
        ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS number
    FROM
        L5
)
,   YEARS AS
(
    SELECT 
        Y.number 
    FROM
        NUMS Y
    WHERE
        Y.number BETWEEN @start / 10000 AND @stop / 10000
)
,   MONTHS AS
(
    SELECT 
        Y.number 
    FROM
        NUMS Y
    WHERE
        Y.number BETWEEN 1 and 12
)
,   DAYS AS
(
    SELECT 
        Y.number 
    FROM
        NUMS Y
    WHERE
        Y.number BETWEEN 1 and 31
)
,  CANDIDATES_0 AS
(
    SELECT
        Y.number * 10000 + M.number * 100 + D.number AS SurrogateKey 
    ,   CAST(Y.number * 10000 + M.number * 100 + D.number AS char(8)) AS DateValue
    FROM 
        YEARS Y
        CROSS APPLY
            MONTHS M
        CROSS APPLY
            DAYS D
)
, HC AS
(
    SELECT
        Y.number * 10000 + M.number * 100 + D.number AS SurrogateKey 
    ,   CAST(Y.number * 10000 + M.number * 100 + D.number AS char(8)) AS DateValue
    FROM 
        YEARS Y
        CROSS APPLY
            MONTHS M
        CROSS APPLY
            DAYS D
    WHERE
        D.number < 31
        AND M.number IN (4,6,9,11)

    UNION ALL
    SELECT
        Y.number * 10000 + M.number * 100 + D.number AS SurrogateKey 
    ,   CAST(Y.number * 10000 + M.number * 100 + D.number AS char(8)) AS DateValue
    FROM 
        YEARS Y
        CROSS APPLY
            MONTHS M
        CROSS APPLY
            DAYS D
    WHERE
        D.number < 32
        AND M.number IN (1,3,5,7,8,10,12)

    UNION ALL
    SELECT
        Y.number * 10000 + M.number * 100 + D.number AS SurrogateKey 
    ,   CAST(Y.number * 10000 + M.number * 100 + D.number AS char(8)) AS DateValue
    FROM 
        YEARS Y
        CROSS APPLY
            MONTHS M
        CROSS APPLY
            DAYS D
    WHERE
        D.number < 29
        AND M.number = 2
        AND
        ( 
            Y.number % 4 > 0
            OR Y.number % 100 = 0 AND Y.number % 400 > 0 
        )

    UNION ALL
    SELECT
        Y.number * 10000 + M.number * 100 + D.number AS SurrogateKey 
    ,   CAST(Y.number * 10000 + M.number * 100 + D.number AS char(8)) AS DateValue
    FROM 
        YEARS Y
        CROSS APPLY
            MONTHS M
        CROSS APPLY
            DAYS D
    WHERE
        D.number < 30
        AND M.number = 2
        AND
        ( 
            Y.number % 4 = 0
            OR Y.number % 100 = 0 AND Y.number % 400 = 0 
        )
)
, CANDIDATES AS
(
    SELECT
        C.SurrogateKey
    ,   CAST(C.DateValue as date) As DateValue
    FROM
        HC C
    WHERE
        ISDATE(c.DateValue) = 1
)
, PARTS 
(
    DateKey
,   FullDateAlternateKey
,   DayNumberOfWeek
,   EnglishDayNameOfWeek
,   DayNumberOfMonth
,   DayNumberOfYear
,   WeekNumberOfYear
,   EnglishMonthName
,   MonthNumberOfYear
,   CalendarQuarter 
,   CalendarYear    
,   CalendarSemester    
--,FiscalQuarter    
--,FiscalYear   
--,FiscalSemester
) AS
(
    SELECT
        CAST(C.SurrogateKey AS int)
    ,   C.DateValue
    ,   DATEPART(WEEKDAY, C.DateValue)
    ,   DATENAME(WEEKDAY, C.DateValue)
    ,   DATEPART(DAY, C.DateValue)
    ,   DATEPART(DAYOFYEAR, C.DateValue)
    ,   DATEPART(WEEK, C.DateValue)
    ,   DATENAME(MONTH, C.DateValue)
    ,   DATEPART(MONTH, C.DateValue)
    ,   DATEPART(QUARTER, C.DateValue)
    ,   DATEPART(YEAR, C.DateValue)
    ,   DATEPART(WEEK, C.DateValue)
    FROM
        CANDIDATES C
    WHERE
        C.DateValue IS NOT NULL
)
SELECT 
    P.*
FROM 
    --HC P
    PARTS P
ORDER BY 1;

Сгенерировав данные, я создал связь между источником и датами и попробовал эту формулу тоже безуспешно

=CALCULATE(SUM(Source[value]), PARALLELPERIOD(Dates[FullDateAlternateKey], -1, year))

Конструктор PowerPivot выглядит как

PowerPivot view

Есть мысли о том, что я делаю не так?

Ссылки

1 Ответ

5 голосов
/ 19 мая 2012

DAX-выражение, которое вы использовали в производном столбце, должно быть показателем и определяться в области вычисления ...

MeasurePriorPeriodValue := CALCULATE(SUM(Source[value]), PARALLELPERIOD(Source[eventDate], -1, year))

... до тех пор, пока столбец, который вы используете в функции parallelperiod, сконфигурирован как тип данных date, он все равно должен работать. Отделение таблицы дат от остальных является «наилучшей практикой», но не обязательно ... потому что она позволяет вам гарантировать отсутствие пробелов (которые могут вызвать проблемы с некоторыми функциями DAX Time-Intelligence) и тому подобное.

...