Embedded Analytics mit CDS Queries - mit Query Template
Veröffentlicht am 22. Dezember 2021 von | ABAP | CDS | S/4HANA |
Was sind CDS Queries?
Das Reporting direkt im transaktionalen ERP System (z.B. S/4HANA) mittels CDS Views wird als Embedded Analytics bezeichnet. Mit den CDS Queries haben wir hierbei die gleichen Möglichkeiten wie bei den SAP BW-Queries aus dem Query Designer. Sie können auch in den selben Tools konsumiert werden, z.B. Transaktion RSRT oder Analysis for Office und in Fiori Kacheln eingebunden werden. In diesem Artikel wollen wir die wichtigsten Elemente der Queries zeigen und am Ende ein Query Template als Kopiervorlage bereit stellen, das als Ausgangsbasis für eigene CDS Queries dienen kann.
Ein Query CDS View kann nur aus einem CDS InfoProvider lesen.
Der CDS InfoProvider wird durch die Annotation @Analytics.DataCategory: #CUBE
oder #DIMENSION
definiert. Er bringt einige Eigenschaften mit, die in der Query geerbt werden. Dazu gehören unter anderem:
- Verknüpfungen vom Cube zu den Dimension Views
- Verknüpfungen von den Dimension Views zu den zugehörigen Text-Views
- Aggregationsverhalten von Kennzahlen
- Semantische Klassifizierung der Felder
- Abhängigkeiten zwischen Feldern
Die CDS InfoProvider modellieren diese Eigenschaften zentral und können in mehreren Queries wiederverwendet werden. Sie entsprechen in vielen Punkten einem Composite Provider im SAP BW. Dem Aufbau von CDS InfoProvidern haben wir einen separaten Blog-Post gewidmet.
Analytic Annotations auf View-Ebene
Ein CDS View wird durch die folgende Analytic Annotation zu einer CDS Query:
@Analytics.query: true
Damit ist der CDS View unter dem Namen des SQL-Views mit dem Präfix 2C in den Tools sichtbar, beispielsweise in der RSRT Transaktion oder dem Analysis for Office. Auf Ebene des Views kann dann noch die Darstellung von Nullen festgelegt werden:
@Analytics.settings.zeroValues: { handling: #HIDE_IF_ALL, // #HIDE, #SHOW
hideOnAxis: #ROWS_COLUMNS // #COLUMNS, #ROWS
}
Analytic Annotations auf Feld-Ebene
In diesem Abschnitt sind die einzelnen Annotationen nach Thema gruppiert. Dabei haben wir jeweils die wichtigsten Annotationen ausgewählt. Für weitere Details empfiehlt sich der Blick in die Referenzdokumentation der SAP.
Für alle Felder kann der Anzeigetext so festgelegt werden:
@EndUserText.label: ''
Parameter zum Filtern in CDS Queries
Eingabeparameter können entweder als CDS Parameter oder, nur zum Filtern, über die Annotation @Consumption.filter
implementiert werden. Die CDS Parameter sind immer Einzelwerte, die beliebig in Ausdrücken verwendet werden können. Beispielsweise in Berechnungen oder als Parameter für SQL-Funktionen. Die Filter über Annotationen sind nicht auf Einzelwerte Beschränkt; Liste von Einzelwerten, Select-Options, einzelne oder mehrere Hierarchieknoten. Die beiden Konzepte können auch kombiniert werden.
@Consumption.filter:{ selectionType: #RANGE, // #INTERVAL, #SINGLE, #HIERARCHY_NODE
multipleSelections: false,
mandatory: true,
hidden: false, //Default: false
defaultValue: '0000000000011675' }
Annotationen für Zeilen (Merkmale)
@AnalyticsDetails.query:{ display: #KEY, //#KEY_TEXT, #TEXT
axis: #ROWS, //#COLUMNS
totals: #HIDE, //#SHOW
hidden: false, //Default: false
sortDirection: #ASC //#DESC
}
Annotationen für Kennzahlen
Kennzahlen werden standardmäßig als Spalte dargestellt. Die zugehörige Annotation kann weggelassen werden. Die Nachkommastellen werden mit decimals
festgelegt und mit scaling
kann der Wert um Zehnerpotenzen verschoben werden. Das ist praktisch, wenn z.B. nur TEUR (=Tausend Euro) statt in EUR berichtet werden soll.
@AnalyticsDetails.query:{ axis: #COLUMNS, //optional - Standard value for keyfigures
decimals: 2, //Decimals
scaling: 0, //Default value - to scale by powers of 10
hidden: false //true = initialy invisible
}
Berechnungen mit Formeln
Mit der Annotation @AnalyticsDetails.query.formula können in der Query Berechnungen durchgeführt werden. Diese werden nur durchgeführt, wenn der CDS View vom OLAP Prozessor verarbeitet wird. Bei einer Datenvorschau sehen wir diese Berechnungen nicht.
@EndUserText.label: 'Profit'
@AnalyticsDetails.query:{ formula: '(price_vk - price_vek) * nodim(quant_b)' }
1 as profit,
Ausnahmeaggregation
@EndUserText.label: 'Anzahl Belege'
@AnalyticsDetails.exceptionAggregationSteps:
[{ exceptionAggregationBehavior: #COUNT,
exceptionAggregationElements: ['doc_number'] }]
1 as doc_count
Annotationen für freie Merkmale
Alle Kennzahlen, die nicht mit der Annotation @AnalyticsDetails.query.axis
auf die Achsen #ROW
und #COLUMN
verteilt wurden, sind freie Merkmale. Das bedeutet, sie sind nicht im initialen Aufriss der Query vorhanden, können aber nach belieben einer der beiden Achsen hinzugefügt werden. Dies wird mit der folgenden, für Merkmale optionalen, Annotation festgelegt:
@AnalyticsDetails.query.axis: #FREE
Das Query Template
Dieses Query Template verwende ich als Kopiervorlage für meine Queries. In den Kommentaren stehen die anderen möglichen Werte für die Annotationen. Die bekommt man zwar auch mit der Code-Completion vorgeschlagen, aber so ist es übersichtlicher, alle Möglichkeiten zu visualisieren.
@AbapCatalog.sqlViewName: 'ZSQL_DEMO_QUERY'
@EndUserText.label: 'Demo Query'
@Analytics.query: true
@Analytics.settings.zeroValues: { handling: #HIDE_IF_ALL, // #HIDE, #SHOW
hideOnAxis: #ROWS_COLUMNS // #COLUMNS, #ROWS
}
define view zcds_demo_Query
as select from ZJB_DEMO_cube
{
///////////////////
// Parameter
///////////////////
@EndUserText.label: 'Kennzahl (Menge)'
@Consumption.filter:{ selectionType: #RANGE, // #INTERVAL, #SINGLE, #HIERARCHY_NODE
multipleSelections: false,
mandatory: true,
hidden: false,
defaultValue: '0000000000011675' }
@AnalyticsDetails.query:{ hidden: true }
measure,
///////////////////
// Merkmale
///////////////////
@AnalyticsDetails.query:{ display: #KEY,
axis: #ROWS,
totals: #HIDE,
sortDirection: #ASC }
calday,
///////////////////
// Kennzahlen
///////////////////
@AnalyticsDetails.query:{ decimals: 4}
price_vk,
@AnalyticsDetails.query.hidden: true
price_vek,
@AnalyticsDetails.query:{ decimals: 0}
quant_b,
// Formel
@EndUserText.label: 'Profit'
@AnalyticsDetails.query:{ formula: '(price_vk - price_vek) * nodim(quant_b)' }
1 as profit,
// Ausnahmeaggregation
@EndUserText.label: 'Unterschiedl. Artikel'
@AnalyticsDetails.exceptionAggregationSteps:
[{ exceptionAggregationBehavior: #COUNT,
exceptionAggregationElements: ['material'] }]
1 as materialCount,
///////////////////
// Freie Merkmale
///////////////////
@EndUserText.label: 'Material'
@AnalyticsDetails.query:{ display: #KEY_TEXT,
axis: #FREE,
totals: #HIDE}
material,
doc_currcy,
base_uom
}
Fazit
Diese Zusammenfassung ist bei meiner Arbeit für das Cheat Sheet CDS Plakat entstanden, da ich die Themen für mich noch etwas sortieren musste. Bislang hatte ich nicht sauber gearbeitet und die Trennung zwischen CDS Queries und CDS InfoProvider war verschwommen. Die Hierarchien habe ich bislang in diesem Beitrag ausgeklammert. Falls ich diese mal benötige und damit Erfahrungen sammele, werde ich das hier noch mit einbringen. Falls Euch noch etwas Wichtiges fehlt, Ihr Fehler entdeckt oder einfach nur Feedback geben wollt, freue ich mich über Kommentare.