From datasphere
Guides creation of Analytic Models in SAP Datasphere for SAP Analytics Cloud: reporting dimensions, calculated/restricted measures, count distinct, currency conversions, exception aggregation. Use for SAC dashboards, KPIs, self-service BI.
npx claudepluginhub mariodefelipe/sap-datasphere-plugin-for-claude-coworkThis skill uses the workspace's default tool permissions.
The Analytic Model Creator skill guides you through designing and implementing Analytic Models in SAP Datasphere. Analytic Models are semantic objects that present data to analytics tools like SAP Analytics Cloud (SAC) in a consumable, pre-aggregated format. They sit above Fact and Dimension views, providing a polished interface for end users to create reports and dashboards.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
The Analytic Model Creator skill guides you through designing and implementing Analytic Models in SAP Datasphere. Analytic Models are semantic objects that present data to analytics tools like SAP Analytics Cloud (SAC) in a consumable, pre-aggregated format. They sit above Fact and Dimension views, providing a polished interface for end users to create reports and dashboards.
An Analytic Model is a semantic object that combines:
Raw Data (Databases)
↓
Data Builder (Cleanse, Join)
↓
Semantic Views (Graphical/SQL)
↓
Analytic Models (Aggregated, Structured) ← YOU ARE HERE
↓
SAC Dashboards, Reports, Exploration
Create an Analytic Model when:
DO NOT use Analytic Models for:
Choose the fact table that contains your measurable events or transactions.
Fact source selection criteria:
Query fact source schema:
Use MCP tool: get_table_schema(fact_view_name)
Returns: column list, data types, key indicators
Fact source example:
SalesOrders Fact View
├── OrderID (Key)
├── OrderDate (Time dimension)
├── CustomerID (Customer dimension key)
├── ProductID (Product dimension key)
├── Amount (Measure)
├── Quantity (Measure)
├── OrderStatus (Attribute)
└── CurrencyCode (Attribute)
Attach dimensional views that provide analysis context.
Dimension selection:
Association mapping: Each dimension is linked via a foreign key association:
SalesOrders.CustomerID → Customer.CustomerID
SalesOrders.ProductID → Product.ProductID
SalesOrders.OrderDate → Date.DateKey
Best practices:
Dimension example:
Customer Dimension
├── CustomerID (Key)
├── CustomerName (Attribute)
├── IndustryCode (Attribute)
├── Region (Attribute, drill-down to Country)
├── SalesTerritory (Attribute)
└── CreditLimit (Attribute)
Measures are the quantifiable metrics users analyze.
Measure types:
Direct aggregation of a fact table column.
Example:
Measure: Total Sales Amount
Source Column: Amount
Aggregation: SUM
Common simple measures:
SUM(Amount) → Total revenue, total costsSUM(Quantity) → Total units soldCOUNT(*) → Number of transactionsAVG(Price) → Average unit priceMIN(Discount) → Minimum discount appliedMAX(OrderValue) → Largest orderDerived from other measures or columns using expressions.
Example:
Measure: Average Order Value
Formula: Total Sales Amount / Number of Orders
Measure: Gross Margin
Formula: (Revenue - COGS) / Revenue
Measure: Days to Delivery
Formula: DATEDIFF(day, OrderDate, DeliveryDate)
Expression examples:
# Percentage calculations
Profit_Margin = Net_Profit / Revenue * 100
# Unit economics
Cost_Per_Unit = Total_Cost / Quantity
# Time-based metrics
Days_In_Inventory = 365 / Inventory_Turnover
# Ratio analysis
Debt_To_Equity = Total_Debt / Total_Equity
Aggregation with specific filter conditions.
Example:
Measure: High-Value Orders
Source: Total Sales Amount
Filter: Amount > 10,000
Measure: On-Time Deliveries
Source: COUNT(OrderID)
Filter: ShipDate <= DueDate
Measure: Completed Orders
Source: COUNT(OrderID)
Filter: Status = 'Completed'
Use cases:
Count unique values of a dimension key.
Example:
Measure: Number of Customers
Type: Count Distinct
Column: CustomerID
Result: Unique customer count
Measure: Product Variety
Type: Count Distinct
Column: ProductID
Result: Number of distinct products sold
Performance consideration:
Measure definition best practices:
execute_query on sample dataSpecify how measures combine across dimensions.
Aggregation types:
| Type | Behavior | Example |
|---|---|---|
| SUM | Add values across dimension | Sum of all order amounts = Total revenue |
| AVG | Average across dimension | Average order value by customer |
| MIN | Minimum value in dimension | Lowest price per product |
| MAX | Highest value in dimension | Highest discount offered |
| COUNT | Count non-null values | Number of orders |
| COUNT DISTINCT | Unique values in dimension | Unique customers |
| NONE | No aggregation (detail level) | Exception cases |
Context-specific aggregation:
Measure: Headcount
SUM by Company (add departments)
AVG by Department (doesn't make sense)
Should use NONE or formula-based
Measure: Salary
AVG by Department (makes sense)
SUM by Department (total payroll)
Attributes provide drill-down paths and detail information for dimensions.
Attribute examples:
From Customer Dimension:
- CustomerName (detail attribute)
- Industry (classification attribute)
- Region (hierarchy attribute)
- SalesRep (responsibility attribute)
From Product Dimension:
- ProductName (detail)
- Category (classification)
- Brand (classification)
- SkuNumber (identifier)
Hierarchy attributes:
Date Dimension
├── Year (top level)
├── Quarter (drill-down)
├── Month (drill-down)
└── Day (detail level)
Geography Dimension
├── Region (top level)
├── Country (drill-down)
├── Province/State (drill-down)
└── City (detail level)
Best practices:
Add dynamic filtering for user interaction.
Variable types:
Users select value(s) before executing queries.
Example:
Variable: FiscalYear
Type: Single-select Prompt
Values: 2022, 2023, 2024
Usage in Measure:
COUNT(Orders) WHERE FiscalYear = :FiscalYear
Multi-select prompt:
Variable: SelectRegions
Type: Multi-select Prompt
Values: North, South, East, West, Europe
Filter: WHERE Region IN (:SelectRegions)
Users specify start and end values.
Example:
Variable: SalesDateRange
Type: Date Range
Filter: WHERE OrderDate BETWEEN :StartDate AND :EndDate
Numeric range:
Variable: OrderAmountRange
Type: Numeric Range
Filter: WHERE Amount >= :MinAmount AND Amount <= :MaxAmount
Predefined values for consistent calculations.
Example:
Variable: CurrentFiscalYear = YEAR(CURRENT_DATE())
Variable: PriorYear = CurrentFiscalYear - 1
Usage: In measures for year-over-year comparisons
Variable best practices:
Handle multi-currency scenarios.
Currency conversion setup:
Define source currency column:
├── CurrencyCode (USD, EUR, GBP, etc.)
Define conversion rules:
├── Target currency (e.g., USD for all reporting)
├── Exchange rate source (lookup table, feed)
├── Effective date matching
└── Rounding rules
Currency conversion configuration:
Measure: Revenue (Converted)
Source: Amount
Original Currency: CurrencyCode column
Target Currency: USD
Exchange Rate Source: ExchangeRate.Lookup (SourceCurrency, TargetCurrency, Date)
Conversion Formula: Amount * ExchangeRate
Multi-currency reporting:
Report users can choose reporting currency:
- Filter: :ReportingCurrency = USD/EUR/GBP
- Measures automatically convert to selected currency
- Reconciliation occurs at transaction level
Best practices:
Define special aggregation behavior for specific measures/dimensions.
Exception aggregation examples:
Specific measure aggregates differently in certain dimension contexts.
Measure: UnitPrice
Normal Aggregation: AVG (average unit price)
Exception with ProductCategory:
- DO NOT average unit prices across product categories
- Use SUM(Amount) / SUM(Quantity) instead (weighted average)
- Prevents misleading aggregations
Use cases:
Dimension behaves differently with certain measures.
Measure: Budget (allocated by department)
Normal behavior: SUM across all dimensions
Exception with Date dimension:
- DO NOT sum budgets across months
- Use only budget for the selected month
- Avoid double-counting
Measure: Headcount (point-in-time)
Exception with Organization:
- DO NOT sum headcount across levels
- Use only at lowest level (employees)
Configuration syntax:
Measure: Commission
Base Aggregation: SUM
Exception Rule:
IF dimension = 'ProductCategory'
THEN aggregate as NONE (show detail only)
ELSE aggregate as SUM
Best practices:
Unique identifiers for dimension members.
CustomerID (Key)
├── Used for dimension uniqueness
├── Not aggregated in reports
├── Used for filtering
└── Links to fact table
Categorical properties for grouping.
Product Category (Classification)
├── Values: Electronics, Clothing, Food
├── Used for drill-down and filtering
├── Typically aggregates with SUM
└── Creates different data segments
Ordered levels for drill-down paths.
Organization Hierarchy:
├── Level 0: Company
├── Level 1: Division
├── Level 2: Department
├── Level 3: Team
└── Level 4: Individual
Longer text fields for context.
Product Description (Text)
├── Marketing description
├── Not aggregated
├── Read-only in most contexts
└── Useful for report context
Data type:
Attribute properties:
Name: ProdCategory
Label: Product Category
Description: "High-level product grouping for analysis"
Data Type: Text
Semantic Role: Classification
Display Length: 50 characters
Variable: SelectedMonth
Type: Single Select
Values: FROM calendar table
Usage: WHERE Month = :SelectedMonth
Variable: FiscalYearRange
Type: Range
Usage: WHERE FiscalYear BETWEEN :StartYear AND :EndYear
Variable: SelectedRegion
Type: Multi-Select
Values: North, South, East, West
Usage: WHERE Region IN (:SelectedRegion)
Variable: CountrySubset
Type: Multi-Select
Dynamic Values: FROM Country dimension
Variable: IndustryFilter
Type: Single Select
Values: Manufacturing, Retail, Service, Government
Usage: WHERE Industry = :IndustryFilter
Variable: MinAnnualRevenue
Type: Numeric
Default: 1000000
Usage: WHERE AnnualRevenue >= :MinAnnualRevenue
Variable: TargetGrowthRate
Type: Numeric
Default: 0.10 (10%)
Usage in Measure: IF(GrowthRate >= :TargetGrowthRate, 'On Track', 'At Risk')
Layout and performance:
Filter interaction:
Naming conventions for clarity:
GOOD:
- "Total Sales Revenue (USD)"
- "Customer Acquisition Cost"
- "On-Time Delivery Rate"
AVOID:
- "SAL_AMT"
- "CALC_COST"
- "OTD_PERC"
Measure organization:
Revenue Measures:
├── Total Sales Amount
├── Average Order Value
├── Revenue by Region
└── Year-over-Year Growth
Cost Measures:
├── Total COGS
├── Operating Expenses
└── Cost Per Unit
Documentation for end users:
For each measure, document:
- What it measures
- How it's calculated
- When to use it
- Any limitations or exceptions
- Currency or unit information
Query optimization:
Dimension cardinality:
Low cardinality (good for filters):
- Department (10-20 values)
- Region (5-10 values)
High cardinality (avoid for filtering):
- Customer ID (millions)
- Transaction ID (billions)
Measure calculation placement:
Retrieve structure and properties of existing analytic models.
Use to understand existing measure definitions and dimension associations
Helps avoid duplicate measures across models
Execute queries against analytic models to validate results.
Use to test measures, filters, and dimension combinations
Verify correct aggregation behavior before deployment
Discover fact tables, dimensions, and existing analytic models.
Use to find suitable fact sources and dimension tables
Identify reusable components
Retrieve detailed column information for fact sources.
Use before creating measures to understand available data
Verify data types and column names
?$filter=Partner_ID eq '100000005' and Value gt 1000000. This enables consumers to request only rows where measures meet specific thresholds, reducing data transfer and improving dashboard performance.