Building Graphical Views: Nodes, Associations, and Semantic Enrichment
Learn how to construct graphical views using projection, join, union, and aggregation nodes, apply semantic types, and configure associations for reusable, performant modeling in Datasphere.
Explanation
Once a consultant understands the object landscape in Data Builder, the next practical skill is building graphical views that transform raw or replicated tables into governed, reusable semantic assets. Graphical views are constructed on a canvas where each node represents a transformation step, and the canvas compiles into an underlying SQL statement executed by the HANA Cloud engine underneath Datasphere. Thinking in terms of node sequencing—rather than a single monolithic query—helps consultants debug performance and logic issues far more efficiently than trying to reason about the generated SQL directly. Core node types: a Projection node selects and optionally renames or calculates columns, and is typically the first node after a source table to control which columns propagate downstream and to reduce data volume early. A Join node combines two inputs on specified key columns with inner, left outer, right outer, or full outer join types; consultants must be deliberate about join type because default inner joins silently drop unmatched rows, which is a frequent source of undercounted report totals in SAC stories. A Union node stacks compatible datasets vertically, useful for combining historical and current-year tables. An Aggregation node performs group-by style summarization, and is often used deliberately to pre-aggregate large fact tables before they reach a join, improving both performance and result correctness (aggregating after a join computed on granular grain can double-count measures if the join produces a fan-out). A Rank node supports top-N style filtering, often used for exception reporting. Semantic usage settings are configured at the view level: consultants mark a view as Fact (for measure-bearing data), Dimension (for descriptive master data), or Text (for translated labels), and this classification directly affects how SAC and the analytic model layer interpret the view's role—Fact views expose measures with aggregation behavior, Dimension views expose attributes and hierarchies. Getting semantic usage wrong (e.g., leaving a large transactional table as a plain 'Relational Dataset' when it should be a Fact) limits how downstream analytic models can use it. Associations are the mechanism for linking a fact view to dimension views without physically joining them at the storage level; they are resolved at query time based on matching key columns, and they enable navigational attributes to be pulled into the fact context lazily. Associations differ from Join nodes in a critical way: a join is resolved and materialized into the view's own result set at build time (well, at query execution against that view), while an association is a metadata-level relationship that is only expanded when a consuming object (like an analytic model) actually requests attributes through it. This lazy-resolution behavior improves performance because unused associations cost nothing at query time, but it also means an association with a broken or ambiguous cardinality won't surface an error until someone tries to use it downstream, so validation during modeling—using the 'Preview Data' feature and checking association cardinality warnings—is essential before publishing. Input parameters can be added to graphical views to support filtering based on runtime values (useful for currency conversion date or fiscal parameters passed from SAC or another consuming view), and these differ from ordinary filter nodes because they must be supplied by the caller rather than being fixed in the view logic. Consultants should also be aware that graphical views can call other graphical or SQL views as sources, forming layered, reusable modeling chains—this is generally preferred over duplicating join logic across multiple views, since a stacked-view approach centralizes maintenance when a source table structure changes.
Code example
-- Simplified illustration of the SQL a graphical view chain might compile to.-- This is representative only; actual generated SQL syntax and structure-- is determined internally by SAP Datasphere and not user-authored in most cases. -- Step 1: Projection node output (selecting relevant columns, early filter)-- SELECT SalesOrderID, CustomerID, ProductID, Quantity, NetAmount, FiscalYear-- FROM RAW_SALES_ORDERS-- WHERE FiscalYear >= 2022 -- Step 2: Aggregation node (pre-aggregate before join to avoid fan-out)-- SELECT CustomerID, ProductID, FiscalYear, SUM(NetAmount) AS TotalNetAmount-- FROM <projection_output>-- GROUP BY CustomerID, ProductID, FiscalYear -- Step 3: Join node (left outer join to preserve all sales rows even if-- a product master record is missing, avoiding silent row loss)-- SELECT agg.*, prod.ProductCategory, prod.ProductName-- FROM <aggregation_output> agg-- LEFT OUTER JOIN DIM_PRODUCT prod-- ON agg.ProductID = prod.ProductID -- Semantic usage for this final view would be set to 'Fact' since it-- carries the measure TotalNetAmount at customer/product/year grain.Real project scenario
A consulting team building a sales analytics model in SAC noticed that revenue totals were roughly 15% higher than the finance team's reconciled figures. Root cause analysis in the Data Builder showed that a graphical view joined a granular sales line-item table directly to a product master table that had multiple historical price-tier records per product, causing a fan-out during the join before aggregation. The fix was to reorder the view logic: aggregate the sales data to the required grain first in an Aggregation node, then join to the dimension afterward, eliminating the duplication and restoring correct totals. The team added a standing review step requiring a 'preview data with row count check' before any fact view was marked exposed.
Common mistakes
• Joining before aggregating, causing fan-out and inflated measure totals • Leaving semantic usage as a generic dataset type instead of explicitly marking Fact or Dimension • Using inner joins by default and unintentionally dropping unmatched rows from the result • Overusing Join nodes for relationships that should be modeled as associations, hurting reusability and performance • Not validating association cardinality, leading to unexpected row multiplication only discovered after downstream consumption • Hardcoding filter values instead of using input parameters, forcing duplicate views for slightly different filter needs
Best practices
• Aggregate fact data to the required reporting grain before joining to dimension tables • Prefer associations over joins when only lazily-consumed descriptive attributes are needed • Explicitly set semantic usage (Fact, Dimension, Text) on every view rather than leaving defaults • Use left outer joins deliberately when referential completeness of the fact side must be preserved • Layer views (projection then aggregation then join) rather than building one dense multi-node view, to simplify debugging • Use input parameters for values that vary by consumer instead of duplicating views with different hardcoded filters • Always preview data and check row counts before marking a view as exposed for consumption
Interview angle
A frequent scenario-based interview question asks candidates to explain why a report shows inflated totals after a join was added to a fact view, testing whether they understand fan-out from one-to-many joins and know that aggregating before joining, or using associations instead of joins for dimension enrichment, is the correct remediation. Candidates should also be able to articulate the practical difference between an association (lazy, metadata-level, resolved on demand) and a join node (resolved within the view's own execution).