Рекурсия в DAX - PullRequest
       24

Рекурсия в DAX

0 голосов
/ 11 октября 2018

Я не знаю, возможно ли это вообще, но я хотел бы иметь возможность создать вычисляемый столбец, в котором каждая строка зависит от строк над ним.

Классическим примером этого является последовательность Фибоначчи , где последовательность определяется рекуррентным отношением 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)

или использовать мелкие диагонали в форме треугольника Паскаля :

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 [Фибоначчи].


Редактировать:

В книге Табло Моделирование в Microsoft SQL Server Analysis Services Марко Руссо и Альберто Феррари, DAX описан и включает в себя этот параграф:

В чистом видеВ функциональном языке DAX нет императивных операторов, но он использует специальные функции, называемые iterators , которые выполняют определенное выражение для каждой строки данного табличного выражения.Эти аргументы близки к лямбда-выражению в функциональных языках.Однако существуют ограничения в способе их объединения, поэтому мы не можем сказать, что они соответствуют определению общего лямбда-выражения.Несмотря на свою функциональную природу, DAX не позволяет вам определять новые функции и не обеспечивает рекурсию.

Кажется, что нет простого способа сделать рекурсию.Мне все еще интересно, есть ли способ сделать это косвенным образом, используя функции Parent-Child , которые кажутся рекурсивными по своей природе.

1 Ответ

0 голосов
/ 23 октября 2018

Исходя из вашего первого примера набора данных, он выглядит для меня как " своего рода " накопленного итога, который, вероятно, можно легко рассчитать в SQL с помощью функции WINDOW - я попробовал пару вещей, но ничего не получилосьтолько пока.Я недостаточно работаю с DAX, чтобы сказать, можно ли это сделать.

Редактировать: При рассмотрении чуть ближе Fibonacci sequence оказывается, что мой код SQL, выполняющий кумулятивное сравнение, не верен.Вы можете прочитать SO Post Как сгенерировать ряд Фибоначчи , и в нем есть несколько хороших 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 Cummulative:

Ссылка, которая может помочь в подсчете совокупных сумм с DAX-- https://www.daxpatterns.com/cumulative-total/. А вот пример кода из статьи.

Cumulative Quantity :=
CALCULATE (
    SUM ( Transactions[Quantity] ),
    FILTER (
        ALL ( 'Date'[Date] ),
        'Date'[Date] <= MAX ( 'Date'[Date] )
    )
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...