DAX中的递归

时间:2018-10-11 17:39:25

标签: dax

我什至不知道这是否可能,但是我希望能够创建一个计算列,其中每一行都取决于其上方的行。

一个典型的例子是Fibonacci sequence,该序列由重复关系F(n) = F(n-1) + F(n-2)和种子F(1) = F(2) = 1定义。

以表格形式,

Index  Fibonacci
----------------
 1      1
 2      1
 3      2
 4      3
 5      5
 6      8
 7     13
 8     21
 9     34
10     55
...    ...

我希望能够将Fibonacci列构造为计算列。

现在,我知道斐波那契数列有一个很好的封闭形式,我可以在其中定义

Fibonacci = (((1 + SQRT(5))/2)^[Index] - ((1 - SQRT(5))/2)^[Index])/SQRT(5)

或使用shallow diagonals of Pascal's triangle form

Fibonacci =
SUMX (
    ADDCOLUMNS (
        SELECTCOLUMNS (
            GENERATESERIES ( 0, FLOOR ( ( [Index] - 1 ) / 2, 1 ) ),
            "ID", [Value]
        ),
        "BinomCoeff", IF (
            [ID] = 0,
            1,
            PRODUCTX (
                GENERATESERIES ( 1, [ID] ),
                DIVIDE ( [Index] - [ID] - [Value], [Value] )
            )
        )
    ),
    [BinomCoeff]
)

但是,对于递归定义的函数,通常不是这种情况(或者出于我实际上对此感兴趣的目的)。


在Excel中,这很容易做到。您将编写这样的公式

A3 = A2 + A1

或采用R1C1表示法

= R[-1]C + R[-2]C

但是我只是不知道在DAX中这是否可能。

我尝试过的所有方法都不起作用,或者给出循环依赖项错误。例如,

Fibonacci = 
VAR n = [Index]
RETURN
IF(Table1[Index] <= 2,
    1,
    SUMX(
        FILTER(Table1,
            Table1[Index] IN {n - 1, n - 2}),
        Table1[Fibonacci]
    )
)

给出错误消息

  

检测到循环依赖关系:表1 [Fibonacci]。


编辑:

Marco Russo和Alberto Ferrari撰写的《 Microsoft SQL Server Analysis Services中的表格建模》一书中描述了DAX,其中包括以下段落:

  

作为一种纯函数式语言,DAX没有命令式语句,但是它利用称为 iterators 的特殊功能,这些功能为给定表表达式的每一行执行特定的表达式。这些参数与函数语言中的lambda表达式非常接近。但是,组合它们的方式存在限制,因此我们不能说它们对应于通用lambda表达式定义。尽管具有功能性,但DAX不允许您定义新功能,并且不提供递归。

似乎没有简单的方法可以进行递归。我仍然不知道是否有一种方法可以使用Parent-Child functions间接地执行此操作,该方法本质上是递归的。

2 个答案:

答案 0 :(得分:1)

根据您的第一个样本数据集,对我来说,它看起来像是“ ”累计总数,可以使用WINDOW函数在SQL中轻松计算出该总和。刚出来。我还没有充分利用DAX来说明是否可以完成。

编辑:在仔细检查Fibonacci sequence时,发现我的SQL代码进行累积比较是不正确的。您可以阅读SO帖子How to generate Fibonacci Series,它提供了一些我测试过的不错的SQL Fibonacci答案;特别是N J - answered Feb 13 '14的帖子。我不确定DAX Fibonacci递归函数的功能。


SQL代码(不太正确):

DECLARE @myTable as table (Indx int)

INSERT INTO @myTable VALUES
    (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)

SELECT
    Indx
    ,SUM(myTable.Indx) OVER(ORDER BY myTable.Indx ASC ROWS BETWEEN UNBOUNDED PRECEDING and CURRENT ROW) -- + myTable.Indx
        AS [Cummulative]
    ,SUM(myTable.Indx) OVER(ORDER BY myTable.Indx ASC ROWS BETWEEN UNBOUNDED PRECEDING and 2 PRECEDING) 
        + SUM(myTable.Indx) OVER(ORDER BY myTable.Indx ASC ROWS BETWEEN UNBOUNDED PRECEDING and 1 PRECEDING) 
        AS [Fibonacci]
from @myTable myTable

结果集:

+------+-------------+-----------+
| Indx | Cummulative | Fibonacci |
+------+-------------+-----------+
| 1    | 1           | NULL      |
+------+-------------+-----------+
| 2    | 3           | NULL      |
+------+-------------+-----------+
| 3    | 6           | 4         |
+------+-------------+-----------+
| 4    | 10          | 9         |
+------+-------------+-----------+
| 5    | 15          | 16        |
+------+-------------+-----------+
| 6    | 21          | 25        |
+------+-------------+-----------+
| 7    | 28          | 36        |
+------+-------------+-----------+
| 8    | 36          | 49        |
+------+-------------+-----------+
| 9    | 45          | 64        |
+------+-------------+-----------+
| 10   | 55          | 81        |
+------+-------------+-----------+

DAX累积:

可以使用DAX https://www.daxpatterns.com/cumulative-total/帮助计算累计总数的链接。这是本文中的一些示例代码。

Cumulative Quantity :=
CALCULATE (
    SUM ( Transactions[Quantity] ),
    FILTER (
        ALL ( 'Date'[Date] ),
        'Date'[Date] <= MAX ( 'Date'[Date] )
    )
)

答案 1 :(得分:1)

DAX语言不支持递归。

它也写在sqlbi关于计算组的文章中

DAX不是递归的,因此计算组不允许递归。这是控制性能的一个好主意,但是与利用递归在MDX Script中可能实现的某些技术相比,它需要一种不同的方法。

https://www.sqlbi.com/blog/marco/2019/03/01/calculation-groups-in-dax-first-impressions/