Ich habe einen Tisch, an dem jede Person für jeden Tag des Jahres einen Rekord hat. Ich habe diese Funktion verwendet, um eine laufende Summe basierend auf der Spalte "Tagesguthaben" zu erzielen
CALCULATE(
SUM(Leave[Daily Balance]),
FILTER(
ALLEXCEPT(Leave, Leave[Employee Id]),
Leave[Date] <= EARLIER(Leave[Date])
))
Aber ich brauche die laufende Summe, um von 1 neu zu starten, wenn Typ = Arbeiten UND die laufende Summe des täglichen Guthabens kleiner als Null ist UND der Typ der vorherigen Zeile nicht gleich Arbeiten ist. Unten sehen Sie einen Screenshot aus Excel. Die erforderliche Funktionsspalte ist das, was ich erreichen muss.
powerbi
dax
powerbi-desktop
LynseyC
quelle
quelle
Antworten:
Dies ist nicht nur eine laufende Summe mit einer Bedingung, sondern auch eine verschachtelte / gruppierte, da die Logik auf der ID-Ebene angewendet werden muss. Bei großen Tabellen ist M besser als DAX, da es nicht so viel RAM benötigt. (Ich habe hier darüber gebloggt : Link zu Blogpost
Die folgende Funktion passt diese Logik an den aktuellen Fall an und muss auf ID-Ebene angewendet werden: (Erforderliche Spaltennamen sind: "Typ", "Tagesgeld", "Anpassungen")
(MyTable as table) => let SelectJustWhatsNeeded = Table.SelectColumns(MyTable,{"Type", "Daily Allowance", "Adjustments"}), ReplaceNulls = Table.ReplaceValue(SelectJustWhatsNeeded,null,0,Replacer.ReplaceValue,{"Adjustments"}), #"Merged Columns" = Table.CombineColumns(ReplaceNulls,{"Daily Allowance", "Adjustments"}, List.Sum,"Amount"), TransformToList = List.Buffer(Table.ToRecords(#"Merged Columns")), ConditionalRunningTotal = List.Skip(List.Generate( () => [Type = TransformToList{0}[Type], Result = 0, Counter = 0], each [Counter] <= List.Count(TransformToList), each [ Result = if TransformToList{[Counter]}[Type] = "working" and [Result] < 0 and [Type] <> "working" then TransformToList{[Counter]}[Amount] else TransformToList{[Counter]}[Amount] + [Result] , Type = TransformToList{[Counter]}[Type], Counter = [Counter] + 1 ], each [Result] )), Custom1 = Table.FromColumns( Table.ToColumns(MyTable) & {ConditionalRunningTotal}, Table.ColumnNames(MyTable) & {"Result"} ) in Custom1
quelle
Überblick
Dies ist eine herausfordernde Aufgabe für PowerBI. Daher ist es möglicherweise schwierig, einen ordentlichen Ansatz zu finden.
Das größte Problem ist, dass das Datenmodell von PowerBI das Konzept einer laufenden Abrechnung nicht unterstützt - zumindest nicht so, wie wir es in Excel tun. In Excel kann eine Spalte auf Werte verweisen, die in der 'vorherigen Zeile' derselben Spalte vorkommen, und dann durch eine in einer anderen Spalte aufgeführte 'tägliche Änderung' angepasst werden.
PowerBI kann dies nur nachahmen, indem alle täglichen Änderungen über eine Teilmenge von Zeilen addiert werden. Wir nehmen den Datumswert in unserer aktuellen Zeile und erstellen eine gefilterte Tabelle, in der alle Daten kleiner als das Datum dieser aktuellen Zeile sind, und fassen dann alle täglichen Änderungen aus dieser Teilmenge zusammen. Dies scheint ein subtiler Unterschied zu sein, ist aber ziemlich bedeutsam:
Dies bedeutet, dass es keine Möglichkeit gibt, unsere laufende Summe zu überschreiben. Die einzige Berechnung, die durchgeführt wird, ist die Spalte mit den täglichen Änderungen - die Spalte mit der 'laufenden Summe' ist nur ein Ergebnis - sie wird niemals in der Berechnung einer nachfolgenden Zeile verwendet.
Wir müssen das Konzept des 'Zurücksetzens' aufgeben und uns stattdessen vorstellen, eine Spalte zu erstellen, die einen 'Anpassungs'-Wert enthält. Unsere Anpassung ist ein Wert, der einbezogen werden kann, sodass bei Erfüllung der beschriebenen Bedingungen die Summe der täglichen Salden und Anpassungen 1 ergibt.
Wenn wir uns den berechneten Lauf von OP ansehen, sehen wir, dass der Wert unserer laufenden Summe an einem "arbeitsfreien" Tag unmittelbar vor einem "arbeitenden" Tag den erforderlichen Betrag ergibt, der, wenn er umgekehrt wird, zu Null und Null summiert Die laufende Summe an jedem folgenden Arbeitstag erhöht sich um eins. Dies ist unser gewünschtes Verhalten (mit einem Problem, das später beschrieben wird).
Ergebnis
Es ist hilfreich, den Unterschied zwischen Zeilen- und Filterkontexten zu kennen und zu wissen, wie EARLIER arbeitet, um dieser Berechnung zu folgen. In diesem Szenario können Sie sich "EARLIER" als "diese Referenz verweist auf den Wert in der aktuellen Zeile" vorstellen, und ansonsten verweist eine Referenz auf die gesamte Tabelle, die von "ALLEXCEPT (Leave, Leave [Id])" zurückgegeben wird Auf diese Weise finden wir die Stellen, an denen die aktuelle Zeile den Typ "Working" und die Zeile des Vortages einen anderen Typ hat.
Diese Berechnung ahmt eine Art "Auffüllen" nach. Darin heißt es: "Wenn Sie alle Zeilen betrachten, deren Datum vor dem Datum in DIESER Zeile liegt, geben Sie den größten Wert in" Letztes Datum vor der Arbeit "zurück."
Jetzt, da jede Zeile ein Feld enthält, in dem erklärt wird, wohin das tägliche Guthaben als Anpassung verwendet werden muss, können wir es einfach von der Tabelle aus nachschlagen.
Und schließlich wenden wir die Anpassung für das Endergebnis auf unsere laufende Summe an.
Die Angelegenheit
Bei diesem Ansatz wird nicht berücksichtigt, dass die Zählung nicht zurückgesetzt werden sollte, es sei denn, der laufende Tagesguthaben liegt unter Null. Ich habe mich zuvor als falsch erwiesen, aber ich würde sagen, dass dies nicht allein im DAX erreicht werden kann, da dadurch eine zirkuläre Abhängigkeit entsteht. Im Wesentlichen stellen Sie eine Anforderung: Verwenden Sie den aggregierten Wert, um zu bestimmen, was in der Aggregation enthalten sein soll.
So weit kann ich dich bringen. Ich hoffe es hilft.
quelle
Ich hoffe, dass Sie beim nächsten Mal eine CSV oder einen Code einfügen, der Beispieldaten anstelle von Bildern generiert. :) :)
Lassen Sie mich nur vorschlagen, dass Sie Ihre Berechnungen stattdessen in PowerQuery durchführen. Ich habe versucht, den Code für einige Schritte aufzuteilen, um die Lesbarkeit zu verbessern. Dies mag etwas komplexer aussehen, funktioniert jedoch gut. Fügen Sie es einfach in den erweiterten Editor ein und ersetzen Sie die Quelle durch Ihre Quelldaten. Viel Glück!
quelle
Ich glaube ich habe es!
Hier ist das Ergebnis, das auf der zuvor veröffentlichten Lösung aufbaut: (Die Daten wurden geändert, um mehr Verhaltensweisen und Anwendungsfälle für "Arbeit / keine Arbeit" anzuzeigen.)
ERGEBNIS
EINZELHEITEN
(1) Löschen Sie die Spalten "Adjusted Running Daily Balance" und "Daily Balance Adjustment". Wir werden in einem Moment das gleiche Ergebnis mit einem Schritt weniger erzielen.
(2) Erstellen Sie die folgende Spalte (RDB = "Running Daily Balance") ...
Nachdem wir das "Letzte Datum vor Abschluss der Arbeit" erstellt haben, haben wir tatsächlich das Stück, das für unser "Zurücksetzen" benötigt wird, von dem ich behauptete, dass es vorher unmöglich war. Durch Filtern nach diesem Feld haben wir die Möglichkeit, jedes Slice bei '1' zu beginnen.
(3) Wir haben immer noch das gleiche Problem, aber wir können das Ergebnis in unserer Spalte nicht betrachten und es verwenden, um zu entscheiden, was später in derselben Spalte zu tun ist. Aber wir KÖNNEN eine neue Anpassungsspalte erstellen, die diese Informationen enthält! Und wir haben bereits einen Verweis auf "Letztes Datum vor der Arbeit" - das ist der letzte Tag in der vorherigen Gruppe ... die Zeile mit den Informationen, die wir brauchen!
Also schauen wir uns den letzten Tag in Each an vorherigen Gruppe an. Wenn die Gesamtsumme dieser Anpassungen einen positiven Wert hat, wenden wir ihn an. Wenn er negativ ist, lassen wir ihn stattdessen in Ruhe. Wenn die ersten Tage unserer Person arbeitsfreie Tage sind, möchten wir dieses anfängliche negative Bit überhaupt nicht in unserer Anpassung haben, damit es auch weggefiltert wird.
(4) Dieser letzte Schritt bringt die Anpassung in das Endergebnis. Fassen Sie die beiden neuen Spalten zusammen und wir sollten endlich unser angepasstes laufendes Tagesguthaben haben. Voila!
Auf dem Weg zu diesem Ergebnis haben wir viele zusätzliche Spalten erstellt, was normalerweise nicht meine Lieblingsbeschäftigung ist. Aber das war eine schwierige Frage.
quelle
Es hat eine Weile gedauert, aber ich konnte eine Problemumgehung finden. Angenommen, der Saldowert für Leerzeichen ist immer -1 und der Wert 1 für "Arbeiten", und diese Daten sind für alle Daten ohne Lücke verfügbar. So etwas wie die folgende Berechnung könnte funktionieren:
Denken Sie daran, dass dies möglicherweise kein fertiges Produkt ist, da ich mit einer kleinen Probe gearbeitet habe, aber dies sollte Ihnen den Einstieg erleichtern. Hoffe das hilft.
quelle
Die Berechnung ist etwas langwierig, scheint aber in den von mir verwendeten Beispieldaten zu funktionieren. Probieren Sie es aus:
Ich habe hier eine Reihe von Variablen verwendet. Vielleicht können Sie sich eine kürzere Version einfallen lassen. Grundsätzlich besteht die Idee darin, das vorherige erste Vorkommen von "Arbeiten" zu finden, um herauszufinden, von wo aus die Berechnung gestartet werden soll. Dies wird in der Variablen "Prev_Blank2" berechnet. Sobald wir den Startpunkt kennen (er beginnt hier mit 1), können wir einfach die Anzahl der Tage mit "Working" oder blank () zwischen Prev_Blank2 und dem Datum des aktuellen Datensatzes zählen. An diesen Tagen können wir den endgültigen Wert für die laufende Summe zurückgeben.
Hoffentlich macht das den Trick;)
quelle