如何使用DAX函数ParallelPeriod?

5
ParaellePeriod函数允许比较不同时期的值(例如,销售额与一年前相比如何)。我在使用它时遇到了问题,但不知道具体是哪个问题。
设置:我创建了一个简单的PowerPivot SQL Server 2008+源查询,并将其命名为“Source”。该查询生成168行数据:6个ID(100-600)和28个日期(从2010年1月至2012年4月每月第一天),并进行了交叉应用。
; 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;

我使用生成的数据创建了Source和Dates之间的关系,并尝试使用此公式,但也没有成功。

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

PowerPivot设计器看起来像这样:

PowerPivot视图

你觉得我做错了什么吗?

参考资料

1个回答

5
您在派生列中使用的DAX表达式应该是一个度量值,并且应该在计算区域中定义...
MeasurePriorPeriodValue := CALCULATE(SUM(Source[value]), PARALLELPERIOD(Source[eventDate], -1, year))

只要您在parallelperiod函数中使用的列已配置为日期数据类型,它仍然可以工作。将日期表与其余内容分开是“最佳实践”,但不是必需的...因为它允许您确保没有间隙(这可能会导致某些DAX时间智能功能出现问题)等等。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接