# Formel-Indikator (/docs/de/indicator-apps/indicators/formula)



Ein **Formel**-Indikator ist eine Metrik, die Ovidens für Sie aus anderen
Indikatoren ermittelt, statt einer, die Sie von Hand eingeben. Sie bauen die
Berechnung einmal auf - "Umsatz minus Kosten" - und Ovidens wertet sie automatisch für
jede Periode und jedes Dimensionsmitglied aus. Wählen Sie am Indikator den Datentyp
**Formel**, und an die Stelle der Erfassungseinstellungen tritt das Feld **Berechnung**.

Eine Berechnung wird **einmal pro Koordinate** ausgewertet. Eine Koordinate ist eine
einzelne **Periode** (zum Beispiel März 2026) plus **ein Mitglied pro Dimension**,
wenn der Indikator Dimensionen hat (zum Beispiel Periode März 2026 mit Region "Nord").
Jede Referenz in der Berechnung wird an dieser Koordinate aufgelöst. Hat eine Eingabe
dort keinen Wert, ist das Ergebnis **leer**, es sei denn, Sie hinterlegen einen
Ersatzwert (siehe [Fehlende Eingaben](#fehlende-eingaben)).

Neu bei Indikator-Apps? Beginnen Sie mit der [Übersicht](../overview.mdx), die
Indikatoren, [Dimensionen und Hierarchien](../dimensions/other-dimensions.mdx) sowie
[Perioden und Zeitgranularität](../dimensions/time.mdx) erklärt.

## Sie bauen eine Berechnung auf, Sie schreiben keine [#sie-bauen-eine-berechnung-auf-sie-schreiben-keine]

Es gibt keine Formelsprache zu lernen. Eine Berechnung entsteht aus einem kleinen Satz
von **Bausteinen**, jeder aus einem Menü gewählt:

* **Referenz** - liest einen anderen Indikator. Nur dieser Baustein liest Daten.
* **Zahl** - ein Wert, den Sie eingeben.
* **Rechnung** - zwei Bausteine mit `+`, `-`, `*` oder `/` dazwischen.
* **Betrag** - der Betrag eines Bausteins, ohne Vorzeichen.
* **Gerundet** - ein Baustein, auf eine Anzahl Nachkommastellen gerundet.
* **Ersatzwert** - ein Baustein plus ein zweiter, der einspringt, wenn der erste leer
  ist.
* **Bedingung** - vergleicht zwei Bausteine und nimmt je nach Antwort einen von zwei
  weiteren.

Jeder Baustein wird aus einer Auswahlliste gewählt, und jeder kann weitere Bausteine
enthalten. Eine Berechnung wie "runde erneuerbare Energie geteilt durch Gesamtenergie,
mal 100, auf eine Nachkommastelle" entsteht also durch Verschachtelung. Der Editor
verlangt nirgends eine Eingabe außer einer Zahl, und es gibt nichts, das Sie falsch
schreiben können.

Unter den Bausteinen zeigt der Editor zwei Zeilen: was Ihre Berechnung in
**Klartext** besagt, und dieselbe Berechnung in der Kurznotation von Ovidens. Die
erste prüfen Sie gegen Ihre Absicht; die zweite ist das, was Fehlermeldungen zitieren.

## Vera baut sie für Sie [#vera-baut-sie-für-sie]

Klicken Sie auf **Metrik beschreiben**, formulieren Sie die Berechnung in eigenen
Worten - etwa "Umsatz minus Kosten" oder "Jahresvergleich des Umsatzwachstums" - und
Vera baut sie auf. Zurück kommt eine echte Berechnung im Editor: Sie können sie
aufklappen, einen Teil ändern und den Rest behalten. Ovidens prüft Veras Antwort,
bevor sie bei Ihnen ankommt - ein Vorschlag, den Sie übernehmen, lässt sich also
speichern.

## Daten lesen: der Baustein Referenz [#daten-lesen-der-baustein-referenz]

Ein Baustein **Referenz** liest genau einen anderen Indikator. Sie wählen den
Indikator aus einer Liste und dann, **wie** er gelesen wird - dafür sind die
Referenzfunktionen da.

Lesen können Sie einen erfassten [numerischen](./input.mdx#numeric) Indikator, einen
erfassten [Ja/Nein](./input.mdx#boolean)-Indikator oder einen anderen
Formel-Indikator. Eine Ja/Nein-Referenz ergibt eine Zahl: **Ja wird zu 1, Nein zu 0**, und
ein fehlender Wert verhält sich wie eine fehlende Zahl. `SUM` über ein Ja/Nein zählt
also, wie viele Perioden das Ziel erreicht haben, und `AVG` ist der Anteil.
Ein [Auswahl](./input.mdx#select)-Indikator wird mit `SELECTED` verglichen, und bei
einem [Text](./input.mdx#text)- oder [Datei](./input.mdx#file)-Indikator lässt sich nur
fragen, ob er überhaupt beantwortet wurde - mit `HAS_VALUE`. Beides steht unten.

### Die Referenzfunktionen [#die-referenzfunktionen]

| Funktion                                                    | Was sie liest                                                                                                         |
| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `VALUE`                                                     | den Wert an dieser Koordinate                                                                                         |
| `SUM` `AVG` `MIN` `MAX` `FIRST` `LAST` `COUNT`              | einen **feiner** erfassten Indikator, verdichtet auf die Periode dieses Indikators                                    |
| `ANCESTOR_SUM` `ANCESTOR_AVG` `ANCESTOR_MIN` `ANCESTOR_MAX` | eine Dimension, **N Ebenen über** dem aktuellen Mitglied verdichtet                                                   |
| `LEVEL_SUM` `LEVEL_AVG` `LEVEL_MIN` `LEVEL_MAX`             | eine Dimension, auf die **absolute Ebene N** verdichtet (1 ist die oberste)                                           |
| `PERIOD_AGO`                                                | den Wert **N Perioden zurück**                                                                                        |
| `YEAR_AGO`                                                  | den Wert genau **ein Jahr zurück**                                                                                    |
| `DIM_SUM`                                                   | die **Summe über alle Mitglieder** einer Dimension                                                                    |
| `MEMBER`                                                    | den Wert **eines benannten Mitglieds**                                                                                |
| `SELECTED`                                                  | ob ein **Auswahl**-Indikator eine bestimmte Option enthält - 1 wenn ja, 0 bei einer anderen                           |
| `HAS_VALUE`                                                 | ob ein Indikator **beliebigen Typs** beantwortet wurde - 1 oder 0, nie leer                                           |
| `MEMBER_COUNT`                                              | **wie viele Mitglieder** eine Dimension auf einer Ebene hat (diese Funktion benennt eine Dimension, keinen Indikator) |

Der Editor fragt nur die Argumente ab, die die gewählte Funktion tatsächlich nimmt.
Wählen Sie `PERIOD_AGO`, fragt er nach der Anzahl Perioden; wählen Sie `MEMBER`, fragt
er nach dem Mitglied; bei `VALUE` fragt er nichts weiter. Wechseln Sie die Funktion,
folgen die Argumente - ein Argument, das die neue Funktion nicht nimmt, kann nicht
zurückbleiben.

**Ebenennummern** begrenzt die Dimension selbst. Eine Hierarchie ist höchstens fünf
Ebenen tief, ein Vorfahrenabstand also höchstens 4 und eine absolute Ebene höchstens
5; `MEMBER_COUNT` kann keine Ebene jenseits der tatsächlichen Tiefe benennen. Der
Editor bietet nur die vorhandenen Ebenen an.

**Zeitverschiebungen.** Bei `PERIOD_AGO` ist die Anzahl eine ganze Zahl von Perioden,
mindestens 1. `YEAR_AGO` landet auf der passenden Periode ein Jahr früher, mit zwei
kleinen Anpassungen, damit es immer eine Vergleichsperiode gibt: eine Periode vom 29.
Februar vergleicht sich mit dem 28. Februar des Vorjahres, und hat das Vorjahr keine
53\. Kalenderwoche, vergleicht sich eine 53.-Wochen-Periode mit dessen letzter Woche.

**Eine Dimension benennen.** Wird ein Indikator über mehr als eine Dimension erfasst,
muss eine Verdichtung wissen, über welche. Der Editor fragt danach - und wenn es nur
eine Möglichkeit gibt, füllt er sie aus und sagt es Ihnen.

**Ein Mitglied wählen.** `MEMBER` liest genau einen Ausschnitt. Das Mitglied muss ein
**Erfassungsmitglied** sein, also eines auf der Ebene, auf der Werte gespeichert
werden; ein übergeordnetes Mitglied ist eine Verdichtung, wofür die Funktionen
`ANCESTOR_*` und `LEVEL_*` da sind. Ein Mitglied zu wählen klappt diese Dimension zu -
ein Indikator ohne eigene Dimensionen kann so einen einzelnen Ausschnitt eines
dimensionierten Indikators lesen.

**Eine Auswahl lesen.** `SELECTED` fragt, ob ein Auswahl-Indikator **eine bestimmte
Option** enthält - Sie wählen die Option aus der Liste dieses Indikators. Die Antwort
ist 1, wenn die Zelle sie enthält, 0 bei einer anderen Option, und **nichts**, wenn die
Zelle nicht beantwortet ist: eine unbeantwortete Frage ist unbekannt und nicht "nicht
diese Option". Legen Sie einen **Ersatzwert** darum, wenn eine unbeantwortete Zelle als
0 zählen soll.

Die Option wird über ihre eigene Identität gemerkt, nicht über ihre Position - ein
**Umsortieren der Optionsliste ändert also nichts** an den Regeln, die sie benennen.
Eine Option zu entfernen, die eine Regel benennt, wird abgelehnt, mit einer Meldung,
die die Option nennt, statt still eine Regel zurückzulassen, die nichts mehr bedeutet.

**Fragen, ob überhaupt geantwortet wurde.** `HAS_VALUE` funktioniert bei einem
Indikator **beliebigen** Typs, auch [Text](./input.mdx#text) und
[Datei](./input.mdx#file), und antwortet an jeder Zelle mit 1 oder 0 - nie leer, auch
dort nicht, wo der Indikator gar keinen gespeicherten Wert hat. Damit wird die
häufigste Fragebogenregel ausdrückbar: *wenn Sie mit Ja geantwortet haben, müssen Sie
den Nachweis anhängen*.

## Fehlende Eingaben [#fehlende-eingaben]

Eine fehlende Eingabe macht das **gesamte Ergebnis leer**, und der Baustein
**Ersatzwert** ist der eine Weg, es anders zu sagen: Er nimmt einen Baustein und einen
zweiten, der einspringt, wenn der erste leer bleibt. Um eine einzelne Referenz gelegt,
setzt er eine Zahl an die Stelle des fehlenden Werts; um eine ganze Teilberechnung
gelegt, deckt er auch das ab, was die Arithmetik selbst erzeugt - eine Division durch
null, ein Ergebnis, das zu groß zum Darstellen ist.

## Ausgearbeitete Beispiele [#ausgearbeitete-beispiele]

Jedes Beispiel unten sind die **Bausteine, die Sie zusammensetzen**, und darunter steht
die Kurznotation, die Ovidens danach unter dem Editor ausgibt. Diese Zeile tippen Sie
nie - sie liest Ihnen Ihre Arbeit zurück, und sie ist die Form, die eine Fehlermeldung
zitiert.

**Marge.** `revenue` und `costs` sind beide monatlich mit denselben Dimensionen, jedes
ist also eine Referenz, gelesen als `VALUE`.

* **Rechnung** mit `-` dazwischen
  * **Referenz** -> `revenue`, gelesen als `VALUE`
  * **Referenz** -> `costs`, gelesen als `VALUE`

```
([revenue] - [costs])
```

**Jahressumme aus Monatsdaten.** In einem jährlichen Indikator liest eine
Zeitverdichtung die Monatsreihe.

* **Referenz** -> `monthly_sales`, gelesen als `SUM`

```
SUM([monthly_sales])
```

**Verhältnis mit Schutz vor Division durch null.** Ein Baustein **Bedingung** gibt 0
zurück, wenn das Ziel null ist.

* **Bedingung**
  * *Wenn dies*: **Referenz** -> `target`, gelesen als `VALUE`
  * *Verglichen mit* `>`: **Zahl** -> 0
  * *Dann nehmen*: **Rechnung** mit `/` zwischen `actual` und `target`
  * *Sonst nehmen*: **Zahl** -> 0

```
IF([target] > 0; ([actual] / [target]); 0)
```

**Jahresvergleich.** Derselbe Indikator zweimal gelesen, einmal wie er steht und einmal
ein Jahr zurück.

* **Rechnung** mit `/` dazwischen
  * **Rechnung** mit `-`: **Referenz** -> `revenue` (`VALUE`) und **Referenz** ->
    `revenue` (`YEAR_AGO`)
  * **Referenz** -> `revenue`, gelesen als `YEAR_AGO`

```
(([revenue] - YEAR_AGO([revenue])) / YEAR_AGO([revenue]))
```

**Anteil an einer Summe.** `energy_consumption` wird über eine Aufschlüsselung
`energy_source` erfasst. Der erneuerbare Anteil ist das Mitglied "renewable" geteilt
durch die Summe über alle Mitglieder, in Prozent, auf eine Stelle gerundet.

* **Gerundet** auf 1 Nachkommastelle
  * **Rechnung** mit `*`
    * **Rechnung** mit `/`: **Referenz** -> `energy_consumption`, gelesen als `MEMBER`
      von `renewable`, und **Referenz** -> `energy_consumption`, gelesen als `DIM_SUM`
    * **Zahl** -> 100

```
ROUND(((MEMBER([energy_consumption]; renewable) / DIM_SUM([energy_consumption])) * 100); 1)
```

Bei 120 erneuerbar von 300 gesamt ergibt das 40.

## Granularitätsregeln [#granularitätsregeln]

Die **Granularität** einer Berechnung ist ihre Zeitgranularität (der Periodentyp) und
ihr Dimensionsumfang (welche Dimensionen, auf welcher Ebene). Referenzen müssen dazu
passen, sonst verweigert Ovidens das Speichern und nennt die Referenz, die nicht passt.

Die Zeithierarchie, von fein nach grob:

```
täglich  <  wöchentlich  <  monatlich  <  quartalsweise  <  jährlich
```

Die Regeln:

* Eine einfache `VALUE`-Referenz muss auf **derselben** Zeitgranularität liegen wie
  der Indikator.
* Ein **feinerer** Indikator muss mit einer Zeitverdichtung gelesen werden (`SUM`,
  `AVG`, `MIN`, `MAX`, `FIRST`, `LAST`, `COUNT`).
* Ein **gröberer** Indikator wird gelesen wie er ist und an jeder feineren Koordinate
  wiederholt. Er wird **nicht** aufgeteilt - teilen Sie ihn selbst, `MEMBER_COUNT` ist
  genau dafür da.
* Eine Referenz auf einer **feineren** Hierarchieebene einer gemeinsamen Dimension muss
  mit `ANCESTOR_*` oder `LEVEL_*` verdichtet werden.
* Eine Referenz, die eine Dimension behält, über die dieser Indikator nicht erfasst
  wird, lässt sich nicht mit ihm vergleichen - Ovidens nennt die Dimension.

## Was Ovidens ablehnt, und wann [#was-ovidens-ablehnt-und-wann]

**Beim Speichern.** Alles daran, wie eine Berechnung **passt**, wird beim Speichern
entschieden, und jede Ablehnung benennt, was nicht gepasst hat:

* eine Referenz auf einen Indikator, den diese App nicht führt, oder auf einen ohne
  numerischen Wert;
* ein **Zyklus** - eine Berechnung, die sich direkt oder über andere selbst liest;
* eine **Erfassungsfrequenz**, die nicht zusammengeht: eine feinere Referenz ohne
  Verdichtung oder eine Verdichtung über eine gröbere;
* eine **Dimension**, die sich nicht ausrichten lässt: eine zusätzliche, über die der
  Indikator nicht erfasst wird, oder eine feinere Ebene ohne Verdichtung;
* ein **Mitglied**, das es nicht gibt oder das ein übergeordnetes statt eines
  Erfassungsmitglieds ist;
* eine **Ebene** jenseits der tatsächlichen Tiefe der Dimension;
* eine schlicht **zu große** Berechnung - es gibt eine Obergrenze für die Anzahl
  Bausteine einer Berechnung und für die Anzahl ihrer Referenzen.

Der Editor stellt beim Bauen dieselbe Frage wie das Speichern - eine Ablehnung
erreicht Sie also als rote Zeile unter der Berechnung und nicht als fehlgeschlagenes
Speichern.

**Bei einem Formel-Indikator.** Eine Zelle hat eine Zahl oder keine. Es gibt keine
Begründung pro Zelle, und das ist Absicht und kein Versäumnis: Ihre Berechnung ist
EINE Anweisung über das gesamte Raster - eine leere Zelle ist also eine, deren
Eingaben dort keinen Wert hatten oder deren Arithmetik dort nicht definiert war, und
die Anweisung kann beides nicht unterscheiden, ohne ein zweites Mal ausgeführt zu
werden.

Eine Begründung bekommt, was **überhaupt nicht** laufen konnte. Dann hat keine Zelle
des Rasters ein Ergebnis, die Begründung steht **einmal** über dem Raster, und jede
Zelle zeigt **Kein Ergebnis** - so wird ein Satz über die Anfrage nicht in jede Zelle
wiederholt, und eine Zelle ohne Ergebnis sieht nie aus wie eine Zelle mit null.

## Wo Ihre Berechnung tatsächlich läuft [#wo-ihre-berechnung-tatsächlich-läuft]

Jede Berechnung wird zu **einer SQL-Anweisung**, die Ovidens erzeugt und mit Ihrer
Konfiguration in Übereinstimmung hält. Sie können sie im Reiter
[Pipeline](../pipeline.mdx) der App vollständig lesen und dort auch die Zeilen sehen, die
sie erzeugt hat - das macht jede Zahl der App überprüfbar.

Die Anweisung ist zum **Lesen** da, nicht zum Bearbeiten und nicht zum einzelnen
Ausführen: Die Pipeline einer Indikator-App gehört Ovidens, sie wird bei jeder Änderung
Ihrer Konfiguration neu geschrieben, und jeder Schritt läuft nur als Teil der Auswertung
dieser App.

Reichen die Bausteine für etwas nicht aus, lesen Sie die Daten mit einem Knoten
[Indikatordaten](../../analytical-apps/pipeline/indicator-data.mdx) in eine
**Analyse-App**. Eine Analyse-App hat einen echten SQL-Editor mit Vorschau und
typisierten Ausgabespalten, und ihre Anweisungen gehören Ihnen.
