參考blog
1,Create an analytical model based on ABAP CDS views
https://blogs.sap.com/2018/03/18/create-an-analytical-model-based-on-abap-cds-views/
2,Create a Multi-Dimensional Report from an Analytical Query
https://developers.sap.com/tutorials/s4hana-kut-create-multi-dimensional-report.html
3,Define the Analytical Query CDS View
https://blogs.sap.com/2017/02/26/step-2-define-the-analytical-query-cds-view/
4,How to create custom Fiori Multidimensional Reporting Application in S/4HANA on-premise
https://blogs.sap.com/2018/07/11/how-to-create-custom-fiori-multidimensional-reporting-application-in-s4hana-on-premise/
數據處理大致可以分成兩大類:聯機事務處理OLTP(on-line transaction processing)、聯機分析處理OLAP(On-Line Analytical Processing)。
OLTP是傳統的關系型數據庫的主要應用,主要是基本的、日常的事務處理,例如銀行交易。OLAP是數據倉庫系統的主要應用,支持復雜的分析操作,側重決策支持,並且提供直觀易懂的查詢結果。
https://www.cnblogs.com/beyondstorm/archive/2006/08/12/475011.html
SAP HANA將OLAP和OLTP處理結合在一個內存數據庫中,事務和分析可以同時存在,這意味着可以實時訪問所需的准確信息。因為我們將事務和分析世界合並在一個數據庫中,所以在基於ABAP CDS(核心數據服務)構建的數據模型時,開發的方式會有一些不同。
當您需要利用聚合的優勢跨不同區域(例如按時間、按位置、按負責人)公開結果時,建議使用分析模型進行報告。這些模型建立在事實(Facts )和維度(Dimensions )之上,這些視圖包含用於進行詳細分析和獲得業務價值的基本數據。
以銷售報告為例,它提供基於客戶、產品、日期和銷售人員的結果。事實(Fact )就是銷售本身,它包含我們可以測量的價值(例如銷售額和總銷售額),根據客戶、產品、時間和銷售人員的過濾器是維度(Dimensions ),這些維度可以附加屬性(Attributes )或文本(Texts )(例如客戶名稱、地址和產品描述),當我們將所有這些維度連接起來時,我們就有了一個多維數據集(Cube ),從而准備了一個分析模型用於消費。
在這個分析模型的基礎上,我們需要構造一個查詢(Query ),以我們希望向用戶公開的方式調整數據。多維數據集必須能夠被一些不同的查詢重用和使用。
例如,使用上面的銷售模型,我們可以在不同的查詢中生成以下指標:
- Sales by year quarter;
- Sales by products with cost above $100;
- Sales by customer located in a specific city;
- Average of sales amount per number of sales;
- Uplift on sales from prior year.
每個查詢將實現特定的目的,並且可以針對不同的應用程序(例如報告、kpi等)進行設計。
CDS的主要目的之一是允許創建語義豐富的數據模型,而注釋是支持這項任務的主要組件。
有許多不同領域的注解,可以通過下面的link進行查看。(注解太難了。資料太少了。)
https://help.sap.com/viewer/cc0c305d2fab47bd808adcad3ca7ee9d/7.5.9/en-US/630ce9b386b84e80bfade96779fbaeec.html
使用abap cds view來創建分析模型,需要使用到cds view的注解:Analytics、AnalyticsDetails。
Analytics 提供了對ABAP CDS視圖的支持,並支持利用數據聚合來使用多維數據。
AnalyticsDetails支持通過更改聚合行為、計划或公式來計算度量,從而調整分析查詢布局。只能在@Analytics.query : true的情況下使用。
如果想要聲明維度、事實、聚合級別或多維數據集,必須在CDS視圖的頭部包含以下注釋:
@Analytics.dataCategory: #VALUE
可以將 #VALUE 替換成下面的項目
- #CUBE
- #AGGREGATIONLEVEL
- #DIMENSION
- #FACT
因為Cubes必須包含至少一個可度量的屬性,要將字段定義為可度量的,需要將此注釋放在字段的頂部:
@DefaultAggregation: #SUM
也可以更改默認聚合,最常見的組合是使用 #SUM 進行聚合
另外需要使用以下注解
@Analytics.query: true
因為定義了聚合模式,查詢必須從多維數據集中(cubes)選擇數據,否則會返回錯誤。
我們以下面的數據模型,進行開發。
創建各個維度的cds view。
1,創建package
2,創建cdsview
DIMENSION: Airline
@AbapCatalog.sqlViewName: 'ZDIMEAIRLINE' @AbapCatalog.compiler.compareFilter: true @AccessControl.authorizationCheck: #CHECK @EndUserText.label: 'Airline' @Analytics.dataCategory: #DIMENSION define view Z_Dimension_Airline as select from scarr { @ObjectModel.text.element: [ 'AirlineName' ] key carrid as Airline, @Semantics.text: true carrname as AirlineName, @Semantics.currencyCode: true currcode as Currency }
DIMENSION: Connection
@AbapCatalog.sqlViewName: 'ZDIMECONNECT' @AbapCatalog.compiler.compareFilter: true @AccessControl.authorizationCheck: #CHECK @EndUserText.label: 'Flight Connection' @Analytics.dataCategory: #DIMENSION @ObjectModel.representativeKey: 'FlightConnection' define view Z_Dimension_Connection as select from spfli association [0..1] to Z_Dimension_Airline as _Airline on $projection.Airline = _Airline.Airline { @ObjectModel.foreignKey.association: '_Airline' key carrid as Airline, @ObjectModel.text.element: [ 'Destination' ] key connid as FlightConnection, @Semantics.text: true concat(cityfrom, concat(' -> ', cityto)) as Destination, _Airline }
DIMENSION: Customer
@AbapCatalog.sqlViewName: 'ZDIMECUSTOMER' @AbapCatalog.compiler.compareFilter: true @AccessControl.authorizationCheck: #CHECK @EndUserText.label: 'Flight Customer' @Analytics.dataCategory: #DIMENSION define view Z_Dimension_Customer as select from scustom association [0..1] to I_Country as _Country on $projection.Country = _Country.Country { @ObjectModel.text.element: [ 'CustomerName' ] key id as Customer, @Semantics.text: true name as CustomerName, @ObjectModel.foreignKey.association: '_Country' @Semantics.address.country: true country as Country, @Semantics.address.city: true city as City, _Country }
DIMENSION: Travel Agency
@AbapCatalog.sqlViewName: 'ZDIMETRVAGENCY' @AbapCatalog.compiler.compareFilter: true @AccessControl.authorizationCheck: #CHECK @EndUserText.label: 'Travel Agency' @Analytics.dataCategory: #DIMENSION define view Z_Dimension_TravelAgency as select from stravelag association [0..1] to I_Country as _Country on $projection.Country = _Country.Country { @ObjectModel.text.element: [ 'TravelAgencyName' ] key agencynum as TravelAgency, @Semantics.text: true name as TravelAgencyName, @ObjectModel.foreignKey.association: '_Country' @Semantics.address.country: true country as Country, @Semantics.address.city: true city as City, _Country }
1. @AbapCatalog.sqlViewName:指定sqlview的名稱,可以在se11中查詢到。
2.@AbapCatalog.compiler.compareFilter:在cdsview的路徑表達式中定義篩選條件的計算。
3.@AccessControl.authorizationCheck:使用DCL進行權限的檢查。
4. @EndUserText.label:元素的短文本。
5. @Analytics.dataCategory: #DIMENSION:所有的維度有需要有該分類。
6. @ObjectModel.text.element:與文本名稱進行關聯。
7. @ObjectModel.foreignKey.association:外部屬性關聯,使用該注解。
8. @ObjectModel.representativeKey:組合主鍵,定義一個代表鍵。
9. @Semantics:幫助定義字段類型。
准備好所有的維度之后,創建cube。
CUBE: Flight Bookings
@AbapCatalog.sqlViewName: 'ZCUBEFLIGHTBOOK' @AbapCatalog.compiler.compareFilter: true @AccessControl.authorizationCheck: #CHECK @EndUserText.label: 'Flight Bookings' @Analytics.dataCategory: #CUBE define view Z_Cube_FlightBookings as select from sbook association [0..1] to I_CalendarDate as _CalendarDate on $projection.FlightDate = _CalendarDate.CalendarDate association [0..1] to Z_Dimension_Airline as _Airline on $projection.Airline = _Airline.Airline association [0..1] to Z_Dimension_Connection as _Connection on $projection.Airline = _Connection.Airline and $projection.FlightConnection = _Connection.FlightConnection association [0..1] to Z_Dimension_Customer as _Customer on $projection.Customer = _Customer.Customer association [0..1] to Z_Dimension_TravelAgency as _TravelAgency on $projection.TravelAgency = _TravelAgency.TravelAgency { /** DIMENSIONS **/ @EndUserText.label: 'Airline' @ObjectModel.foreignKey.association: '_Airline' carrid as Airline, @EndUserText.label: 'Connection' @ObjectModel.foreignKey.association: '_Connection' connid as FlightConnection, @EndUserText.label: 'Flight Date' @ObjectModel.foreignKey.association: '_CalendarDate' fldate as FlightDate, @EndUserText.label: 'Book No.' bookid as BookNumber, @EndUserText.label: 'Customer' @ObjectModel.foreignKey.association: '_Customer' customid as Customer, @EndUserText.label: 'Travel Agency' @ObjectModel.foreignKey.association: '_TravelAgency' agencynum as TravelAgency, @EndUserText.label: 'Flight Year' _CalendarDate.CalendarYear, @EndUserText.label: 'Flight Month' _CalendarDate.CalendarMonth, @EndUserText.label: 'Customer Country' @ObjectModel.foreignKey.association: '_CustomerCountry' _Customer.Country as CustomerCountry, @EndUserText.label: 'Customer City' _Customer.City as CustomerCity, @EndUserText.label: 'Travel Agency Country' @ObjectModel.foreignKey.association: '_TravelAgencyCountry' _TravelAgency.Country as TravelAgencyCountry, @EndUserText.label: 'Travel Agency Customer City' _TravelAgency.City as TravelAgencyCity, /** MEASURES **/ @EndUserText.label: 'Total of Bookings' @DefaultAggregation: #SUM 1 as TotalOfBookings, @EndUserText.label: 'Weight of Luggage' @DefaultAggregation: #SUM @Semantics.quantity.unitOfMeasure: 'WeightUOM' luggweight as WeightOfLuggage, @EndUserText.label: 'Weight Unit' @Semantics.unitOfMeasure: true wunit as WeightUOM, @EndUserText.label: 'Booking Price' @DefaultAggregation: #SUM @Semantics.amount.currencyCode: 'Currency' forcuram as BookingPrice, @EndUserText.label: 'Currency' @Semantics.currencyCode: true forcurkey as Currency, // Associations _Airline, _CalendarDate, _CalendarDate._CalendarMonth, _CalendarDate._CalendarYear, _Connection, _Customer, _Customer._Country as _CustomerCountry, _TravelAgency, _TravelAgency._Country as _TravelAgencyCountry }
1. 不用必須使用cube去構造fact數據集,可以直接公開在cube中定義的表,來避免使用過多的層級。fact視圖不能有連接或者關聯,只包含可度量的值,如果要連接維度,要使用cube而不是fact。
2. @Analytics.dataCategory: #CUBE:所有的cube需要使用該分類。
3. @DefaultAggregation:該字段用來進行度量。
4. 所有關聯都暴露在視圖的底部,以便在查詢使用期間提供對屬性和文本的訪問。
使用tcode(RSRTS_ODP_DIS)。該事務用於檢查放置在分析數據模型中的關聯、文本和層次結構,為每個屬性提供詳細的分析。
將創建的sqlviewname放入odp name中,點擊執行。
消費view,進行query
QUERY: Flight Bookings
@AbapCatalog.sqlViewName: 'ZQUERYFLIGHTBOOK' @AbapCatalog.compiler.compareFilter: true @AccessControl.authorizationCheck: #CHECK @EndUserText.label: 'Flight Bookings' @Analytics.query: true @VDM.viewType: #CONSUMPTION define view Z_Query_FlightBookings as select from Z_Cube_FlightBookings { /** DIMENSIONS **/ @AnalyticsDetails.query.display: #KEY_TEXT @AnalyticsDetails.query.axis: #FREE Airline, @AnalyticsDetails.query.display: #KEY_TEXT @AnalyticsDetails.query.axis: #FREE FlightConnection, @AnalyticsDetails.query.display: #KEY @AnalyticsDetails.query.axis: #FREE FlightDate, @AnalyticsDetails.query.display: #KEY_TEXT @AnalyticsDetails.query.axis: #FREE Customer, @AnalyticsDetails.query.display: #KEY_TEXT @AnalyticsDetails.query.axis: #FREE TravelAgency, @AnalyticsDetails.query.display: #KEY @AnalyticsDetails.query.axis: #FREE CalendarYear, @AnalyticsDetails.query.display: #TEXT @AnalyticsDetails.query.axis: #FREE CalendarMonth, @AnalyticsDetails.query.display: #TEXT @AnalyticsDetails.query.axis: #FREE CustomerCountry, @AnalyticsDetails.query.display: #KEY @AnalyticsDetails.query.axis: #FREE CustomerCity, @AnalyticsDetails.query.display: #TEXT @AnalyticsDetails.query.axis: #FREE TravelAgencyCountry, @AnalyticsDetails.query.display: #KEY @AnalyticsDetails.query.axis: #FREE TravelAgencyCity, @AnalyticsDetails.query.display: #KEY @AnalyticsDetails.query.axis: #FREE Currency, @AnalyticsDetails.query.display: #KEY @AnalyticsDetails.query.axis: #FREE WeightUOM, /** MEASURES **/ TotalOfBookings, WeightOfLuggage, BookingPrice, @EndUserText.label: 'Average Weight Per Flight' @AnalyticsDetails.exceptionAggregationSteps.exceptionAggregationBehavior: #AVG @AnalyticsDetails.exceptionAggregationSteps.exceptionAggregationElements: [ 'Airline', 'FlightConnection', 'FlightDate' ] @AnalyticsDetails.query.formula: '$projection.WeightOfLuggage' @AnalyticsDetails.query.decimals: 0 0 as AverageWeightPerFlight }
可以用一般的sql語句對view進行查詢。
SELECT SUM("Quantity") FROM "MyProducts" WHERE "Product_Name" IN ('Jackets', 'Coats');
1. 所有的query需要設置@Analytics.query: true
2. @AnalyticsDetails用於進行查詢,提供以下功能:
@AnalyticsDetails.query.display: #KEY_TEXT:設置顯示key還是text。i.e EmployeeName for Employee.
@AnalyticsDetails.query.axis:定位元素的軸
@AnalyticsDetails.exceptionAggregationSteps.exceptionAggregationBehavior:進行例外聚合運算
@AnalyticsDetails.exceptionAggregationSteps.exceptionAggregationElements:進行例外聚合運算時,使用的列
@AnalyticsDetails.query.formula:計算公式
@AnalyticsDetails.query.decimals:小數點位數
3,測試查詢結果
登陸friori管理頁面,建立tile與對應的target
tile
target
Semantic Object、action要與tile的值設置為一致。
URL、ID需要指定為固定的值。
參數中的,XQUERY,需要設置為上面實現的sqlviewname加前綴2C。XSYSTEM需要設置為LOCAL,我感覺是需要與segw中的service maintenance中設置的一致。
其他的一些參數可以參照最上面的blog。
之后登陸fiori launchpad點擊tile進入。