SlideShare a Scribd company logo
Cubing and Metrics in
SQL, oh my!
Julian Hyde (Google)
Data Council • Austin, TX • 2023-03-29
SQL vs BI
BI tools implement their own languages on top of SQL. Why not SQL?
Possible reasons:
● Semantic Model
● Control presentation / visualization
● Governance
● Pre-join tables
● Define reusable calculations
● Ask complex questions in a concise way
Processing BI in SQL
Why we should do it
● Move processing, not data
● Cloud SQL scale
● Remove data lag
● SQL is open
Why it’s hard
● Different paradigm
● More complex data model
● Can’t break SQL
What’s this talk about?
Extensions to Apache Calcite’s SQL dialect
Adoption by other SQL engines?
Rethinking the “semantic model” and “metrics layer”
An API for data?
Pasta machine vs Pizza delivery
Relational algebra (bottom-up) Multidimensional (top-down)
Products
Suppliers
⨝
⨝
Σ
⨝
σ
Sales
Products
Suppliers
⨝
⨝
Σ
σ
Sales
π
(Supplier:
‘ACE’,
Date: 2022-01’,
Product: all)
(Supplier:
‘ACE’,
Date: 2023-01’,
Product: all)
Supplier
Product
Date
Bottom-up vs Top-down query
A multidimensional query #1
Select top 5 suppliers for each product category for
last year, based on total sales.
A multidimensional query #2
For each product category, select total sales this
month of the product that had highest sales in that
category last month.
A multidimensional query #3
For supplier “Ace” and for each product, give the
fractional increase in the sales in January 2023
relative to the sales in January 2022.
Query:
● For supplier “Ace” and for each product, give the fractional increase in the sales in January 2023 relative to
the sales in January 2022.
SQL MDX
SELECT p.prodId,
s95.sales,
(s95.sales - s94.sales) / s95.sales
FROM (
SELECT p.prodId, SUM(s.sales) AS sales
FROM Sales AS s
JOIN Suppliers AS u USING (suppId)
JOIN Products AS p USING (prodId)
WHERE u.name = ‘ACE’
AND FLOOR(s.date TO MONTH) = ‘2023-01-01’
GROUP BY p.prodId) AS s95
LEFT JOIN (
SELECT p.prodId, SUM(s.sales) AS sales
FROM Sales AS s
JOIN Suppliers AS u USING (suppId)
JOIN Products AS p USING (prodId)
WHERE u.name = ‘ACE’
AND FLOOR(s.date TO MONTH) = ‘2022-01-01’
GROUP BY p.prodId) AS s94
USING (prodId)
WITH MEMBER [Measures].[Sales Last Year] =
([Measures].[Sales],
ParallelPeriod([Date], 1, [Date].[Year]))
MEMBER [Measures].[Sales Growth] =
([Measures].[Sales]
- [Measures].[Sales Last Year])
/ [Measures].[Sales Last Year]
SELECT [Measures].[Sales Growth] ON COLUMNS,
[Product].Members ON ROWS
FROM [Sales]
WHERE ([Supplier].[ACE], [Date].[1995].[Jan])
Query:
● For supplier “Ace” and for each product, give the fractional increase in the sales in January 2023 relative to
the sales in January 2022.
SQL SQL with measures
SELECT p.prodId,
s95.sales,
(s95.sales - s94.sales) / s95.sales
FROM (
SELECT p.prodId, SUM(s.sales) AS sales
FROM Sales AS s
JOIN Suppliers AS u USING (suppId)
JOIN Products AS p USING (prodId)
WHERE u.name = ‘ACE’
AND FLOOR(s.date TO MONTH) = ‘2023-01-01’
GROUP BY p.prodId) AS s95
LEFT JOIN (
SELECT p.prodId, SUM(s.sales) AS sales
FROM Sales AS s
JOIN Suppliers AS u USING (suppId)
JOIN Products AS p USING (prodId)
WHERE u.name = ‘ACE’
AND FLOOR(s.date TO MONTH) = ‘2022-01-01’
GROUP BY p.prodId) AS s94
USING (prodId)
SELECT p.prodId,
SUM(s.sales) AS MEASURE sumSales,
sumSales AT (SET FLOOR(s.date TO MONTH)
= ‘2022-01-01’)
AS MEASURE sumSalesLastYear
FROM Sales AS s
JOIN Suppliers AS u USING (suppId)
JOIN Products AS p USING (prodId))
WHERE u.name = ‘ACE’
AND FLOOR(s.date TO MONTH) = ‘2023-01-01’
GROUP BY p.prodId
Self-joins, correlated subqueries, window aggregates, measures
Window aggregate functions were introduced to save on
self-joins.
Some DBs rewrite scalar subqueries and self-joins to
window aggregates [Zuzarte2003].
Window aggregates are more concise, easier to optimize,
and often more efficient.
However, window aggregates can only see data that is from
the same table, and is allowed by the WHERE clause.
Measures overcome that limitation.
SELECT *
FROM Employees AS e
WHERE sal > (
SELECT AVG(sal)
FROM Employees
WHERE deptno = e.deptno)
SELECT *
FROM Employees AS e
WHERE sal > AVG(sal)
OVER (PARTITION BY deptno)
A measure is…
… a column with an aggregate function. SUM(sales)
… a column that, when used as an
expression, knows how to aggregate itself.
(SUM(sales) - SUM(cost))
/ SUM(sales)
… a column that, when used as expression,
can evaluate itself in any context.
Its value depends on, and only on, the
predicate placed on its dimensions.
(SELECT SUM(forecastSales)
FROM SalesForecast AS s
WHERE predicate(s))
ExchService$ClosingRate(
‘USD’, ‘EUR’, sales.date)
SELECT MOD(deptno, 2) = 0 AS evenDeptno, avgSal2
FROM
WHERE deptno < 30
SELECT deptno, AVG(avgSal) AS avgSal2
FROM
GROUP BY deptno
Table model
Tables are SQL’s fundamental
model.
The model is closed – queries
consume and produce tables.
Tables are opaque – you can’t
deduce the type, structure or
private data of a table.
SELECT deptno, job,
AVG(sal) AS avgSal
FROM Employees
GROUP BY deptno, job
SELECT e.deptno, e.job, d.dname, e.avgSal / e.deptAvgSal
FROM
AS e
JOIN Departments AS d USING (deptno)
WHERE d.dname <> ‘MARKETING’
GROUP BY deptno, job
We propose to allow any table and
query to have measure columns.
The model is closed – queries
consume and produce
tables-with-measures.
Tables-with-measures are
semi-opaque – you can’t deduce the
type, structure or private data, but
you can evaluate the measure in any
context that can be expressed as a
predicate on the measure’s
dimensions.
SELECT *,
avgSal AS MEASURE avgSal,
avgSal AT (CLEAR deptno) AS MEASURE deptAvgSal
FROM
Table model with measures
SELECT *,
AVG(sal) AS MEASURE avgSal
FROM Employees
Model + Query + Engine = Data system
Query
language
Data
model
Engine
Syntax
expression AS MEASURE name – defines a measure in the SELECT clause
AGGREGATE(measure) – evaluates a measure in a GROUP BY query
expression AT (contextModifier…) – evaluates expression in a modified context
contextModifier ::=
CLEAR dimension [, dimension… ]
| CLEAR ALL [ EXCEPT dimension [, dimension… ] ]
| SET dimension = [CURRENT] expression
| VISIBLE
| ALL
aggFunction(aggFunction(expression) PER dimension) – multi-level aggregation
Plan of attack
1. Add measures to the table model, and allow queries to use them
◆ Measures are defined only via the Table API
2. Define measures using SQL expressions (AS MEASURE)
◆ You can still define them using the Table API
3. Context-sensitive expressions (AT)
Semantics
0. We have a measure M, value type V,
in a table T.
CREATE VIEW AnalyticEmployees AS
SELECT *, AVG(sal) AS MEASURE avgSal
FROM Employees
1. System defines a row type R with the
non-measure columns.
CREATE TYPE R AS
ROW (deptno: INTEGER, job: VARCHAR)
2. System defines an auxiliary function
for M. (Function is typically a scalar
subquery that references the measure’s
underlying table.)
CREATE FUNCTION computeAvgSal(
rowPredicate: FUNCTION<R, BOOLEAN>) =
(SELECT AVG(e.sal)
FROM Employees AS e
WHERE APPLY(rowPredicate, e))
Semantics (continued)
3. We have a query that uses M. SELECT deptno,
avgSal
/ avgSal AT (CLEAR deptno)
FROM AnalyticEmployees AS e
GROUP BY deptno
4. Substitute measure references with
calls to the auxiliary function with the
appropriate predicate
SELECT deptno,
computeAvgSal(r → (r.deptno = e.deptno))
/ computeAvgSal(r → TRUE))
FROM AnalyticEmployees AS e
GROUP BY deptno
5. Planner inlines computeAvgSal and
scalar subqueries
SELECT deptno, AVG(sal) / MIN(avgSal)
FROM (
SELECT deptno, sal,
AVG(sal) OVER () AS avgSal
FROM Employees)
GROUP BY deptno
Calculating at the right grain
Example Formula Grain
Computing the revenue from
units and unit price
units * pricePerUnit AS revenue Row
Sum of revenue (additive) SUM(revenue)
AS MEASURE sumRevenue
Top
Profit margin (non-additive) (SUM(revenue) - SUM(cost))
/ SUM(revenue)
AS MEASURE profitMargin
Top
Inventory (semi-additive) SUM(LAST_VALUE(unitsInStock)
PER inventoryDate)
AS MEASURE sumInventory
Intermediate
Daily average (weighted
average)
AVG(sumRevenue PER orderDate)
AS MEASURE dailyAvgRevenue
Intermediate
Subtotals & visible
SELECT deptno, job,
SUM(sal), sumSal
FROM (
SELECT *,
SUM(sal) AS MEASURE sumSal
FROM Employees)
WHERE job <> ‘ANALYST’
GROUP BY ROLLUP(deptno, job)
ORDER BY 1,2
deptno job SUM(sal) sumSal
10 CLERK 1,300 1,300
10 MANAGER 2,450 2,450
10 PRESIDENT 5,000 5,000
10 8,750 8,750
20 CLERK 1,900 1,900
20 MANAGER 2,975 2,975
20 4,875 10,875
30 CLERK 950 950
30 MANAGER 2,850 2,850
30 SALES 5,600 5,600
30 9,400 9,400
20,750 29,025
Measures by default sum ALL rows;
Aggregate functions sum only VISIBLE rows
Visible
Expression Example Which rows?
Aggregate function SUM(sal) Visible only
Measure sumSal All
AGGREGATE applied to measure AGGREGATE(sumSal) Visible only
Measure with VISIBLE sumSal AT (VISIBLE) Visible only
Measure with ALL sumSal AT (ALL) All
Measures don’t require GROUP BY
Evaluating a measure on each row SELECT deptno,
avgSal
FROM AnalyticEmployees AS e
Evaluating a measure on a window of
several rows
SELECT deptno,
avgSal OVER (PARTITION BY job
ORDER BY hiredate
RANGE ‘1’ YEAR PRECEDING)
FROM AnalyticEmployees AS e
Semantic models versus databases
In my opinion, a semantic model…
● … is the place to share data and calculations
● … needs a really good query language
○ (So you don’t have to change the model every time
someone has a new question)
● … doesn’t become a database just because it
speaks SQL
● … should do other things too
○ (Access control, governance, presentation defaults,
guide data exploration, transform data, tune data, …)
Shouldn’t the semantic model
be outside the database?
(I don’t want to be tied to one
DBMS vendor.)
I have a great semantic model
already. Why do I need a query
language? My users don’t want
to write SQL.
What even is a
semantic model?
Summary
Top-down evaluation makes queries concise
Measures make calculations reusable
Measures don’t break SQL
References
Papers
● [Agrawal1997] “Modeling multidimensional databases” (Agrawal, Gupta, and Sarawagi, 1997)
● [Zuzarte2003] “WinMagic: Subquery Elimination Using Window Aggregation” (Zuzarte, Pirahash, Ma,
Cheng, Liu, and Wong, 2003)
Issues
● [CALCITE-4488] WITHIN DISTINCT clause for aggregate functions (experimental)
● [CALCITE-4496] Measure columns ("SELECT ... AS MEASURE")
● [CALCITE-5105] Add MEASURE type and AGGREGATE aggregate function
● [CALCITE-5155] Custom time frames
● [CALCITE-xxxx] PER
● [CALCITE-xxxx] AT
Thank you!
Any questions?
@julianhyde
@ApacheCalcite
https://calcite.apache.org
Slides and recording will be posted at @julianhyde
Appendix
Abstract
If SQL is the universal language of data, why do we author our most important data applications (metrics, analytics, business intelligence) in
languages other than SQL? Multidimensional databases and languages such as MDX, DAX and Tableau LOD solve these problems but
introduce others: they require specialized knowledge, complicate the data pipeline and don’t integrate well. Is it possible to define and query
business intelligence models in SQL?
Apache Calcite has extended SQL to support metrics (which we call ‘measures’), filter context, and analytic expressions. With these concepts
you can define data models (which we call Analytic Views) that contain metrics, use them in queries, and define new metrics in queries.
In this talk by the original developer of Apache Calcite, we describe the SQL syntax extensions for metrics,
and how to use them for cross-dimensional calculations such as period-over-period, percent-of-total,
non-additive and semi-additive measures. We describe how we got around fundamental limitations in SQL
semantics, and approaches for optimizing queries that use metrics.
ABOUT THE SPEAKER
Julian Hyde is the original developer of Apache Calcite, an open source framework for building data
management systems, and Morel, a functional query language. Previously he created Mondrian, an analytics
engine, and SQLstream, an engine for continuous queries. He is a staff engineer at Google, where he works
on Looker and BigQuery.
Some multidimensional queries
● Give the total sales for each product in each quarter of 1995. (Note that quarter is a function of date).
● For supplier “Ace” and for each product, give the fractional increase in the sales in January 1995 relative to
the sales in January 1994.
● For each product give its market share in its category today minus its market share in its category in
October 1994.
● Select top 5 suppliers for each product category for last year, based on total sales.
● For each product category, select total sales this month of the product that had highest sales in that
category last month.
● Select suppliers that currently sell the highest selling product of last month.
● Select suppliers for which the total sale of every product increased in each of last 5 years.
● Select suppliers for which the total sale of every product category increased in each of last 5 years.
From [Agrawal1997]. Assumes a database with dimensions {supplier, date, product} and measure {sales}.)

More Related Content

PPT
Sql Tutorials
Priyabrat Kar
 
PPTX
Sql joins
Gaurav Dhanwant
 
PDF
SQL Joins With Examples | Edureka
Edureka!
 
DOCX
" PMT FUNCTION WITH EXAMPLE " IN MS EXCEL
rahul kumar
 
PPT
Προβλήματα γεωμετρίας
Γιάννης Φερεντίνος
 
PPTX
Sql joins inner join self join outer joins
Deepthi Rachumallu
 
DOCX
Eam Activity Association Template
Baker Khader Abdallah, PMP
 
PDF
Adding measures to Calcite SQL
Julian Hyde
 
Sql Tutorials
Priyabrat Kar
 
Sql joins
Gaurav Dhanwant
 
SQL Joins With Examples | Edureka
Edureka!
 
" PMT FUNCTION WITH EXAMPLE " IN MS EXCEL
rahul kumar
 
Προβλήματα γεωμετρίας
Γιάννης Φερεντίνος
 
Sql joins inner join self join outer joins
Deepthi Rachumallu
 
Eam Activity Association Template
Baker Khader Abdallah, PMP
 
Adding measures to Calcite SQL
Julian Hyde
 

Similar to Cubing and Metrics in SQL, oh my! (20)

PPTX
Intro to DAX Patterns
Eric Bragas
 
PDF
Building a semantic/metrics layer using Calcite
Julian Hyde
 
PPTX
Getting power bi
Umakant Bhardwaj
 
PDF
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Julian Hyde
 
PPTX
Business Intelligence Portfolio
Chris Seebacher
 
PPTX
Dax formulas in power bi.pptx data analytics
hiratayyabi123
 
PPT
PHP mysql Aggregate functions
Mudasir Syed
 
PPTX
Exploring Advanced SQL Techniques Using Analytic Functions
Zohar Elkayam
 
PPTX
Exploring Advanced SQL Techniques Using Analytic Functions
Zohar Elkayam
 
PPTX
Lesson-5-Complex-Queries-Aggregate-Function-Nested-Queries-Triggers.pptx
barorojason35
 
PDF
Calculation Groups - color 1 slide per page.pdf
PBIMINERADC
 
PDF
Oracle_Analytical_function.pdf
KalyankumarVenkat1
 
ODP
SQL Tunning
Dhananjay Goel
 
PPTX
Oracle: Functions
oracle content
 
PPTX
Oracle: Functions
DataminingTools Inc
 
PDF
Funções DAX.pdf
Joao Vaz
 
PPTX
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
PDF
Oracle Advanced SQL and Analytic Functions
Zohar Elkayam
 
PPTX
Simplifying SQL with CTE's and windowing functions
Clayton Groom
 
PPTX
fdocuments.in_the-model-clause-explained (1).pptx
hesham alataby
 
Intro to DAX Patterns
Eric Bragas
 
Building a semantic/metrics layer using Calcite
Julian Hyde
 
Getting power bi
Umakant Bhardwaj
 
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Julian Hyde
 
Business Intelligence Portfolio
Chris Seebacher
 
Dax formulas in power bi.pptx data analytics
hiratayyabi123
 
PHP mysql Aggregate functions
Mudasir Syed
 
Exploring Advanced SQL Techniques Using Analytic Functions
Zohar Elkayam
 
Exploring Advanced SQL Techniques Using Analytic Functions
Zohar Elkayam
 
Lesson-5-Complex-Queries-Aggregate-Function-Nested-Queries-Triggers.pptx
barorojason35
 
Calculation Groups - color 1 slide per page.pdf
PBIMINERADC
 
Oracle_Analytical_function.pdf
KalyankumarVenkat1
 
SQL Tunning
Dhananjay Goel
 
Oracle: Functions
oracle content
 
Oracle: Functions
DataminingTools Inc
 
Funções DAX.pdf
Joao Vaz
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
Oracle Advanced SQL and Analytic Functions
Zohar Elkayam
 
Simplifying SQL with CTE's and windowing functions
Clayton Groom
 
fdocuments.in_the-model-clause-explained (1).pptx
hesham alataby
 
Ad

More from Julian Hyde (20)

PDF
Morel, a data-parallel programming language
Julian Hyde
 
PDF
Is there a perfect data-parallel programming language? (Experiments with More...
Julian Hyde
 
PDF
Morel, a Functional Query Language
Julian Hyde
 
PDF
Apache Calcite (a tutorial given at BOSS '21)
Julian Hyde
 
PDF
The evolution of Apache Calcite and its Community
Julian Hyde
 
PDF
What to expect when you're Incubating
Julian Hyde
 
PDF
Open Source SQL - beyond parsers: ZetaSQL and Apache Calcite
Julian Hyde
 
PDF
Efficient spatial queries on vanilla databases
Julian Hyde
 
PDF
Smarter Together - Bringing Relational Algebra, Powered by Apache Calcite, in...
Julian Hyde
 
PDF
Tactical data engineering
Julian Hyde
 
PDF
Don't optimize my queries, organize my data!
Julian Hyde
 
PDF
Spatial query on vanilla databases
Julian Hyde
 
PDF
Data all over the place! How SQL and Apache Calcite bring sanity to streaming...
Julian Hyde
 
PDF
Apache Calcite: A Foundational Framework for Optimized Query Processing Over ...
Julian Hyde
 
PPTX
Lazy beats Smart and Fast
Julian Hyde
 
PDF
Don’t optimize my queries, optimize my data!
Julian Hyde
 
PDF
Data profiling with Apache Calcite
Julian Hyde
 
PDF
A smarter Pig: Building a SQL interface to Apache Pig using Apache Calcite
Julian Hyde
 
PDF
Data Profiling in Apache Calcite
Julian Hyde
 
PDF
Streaming SQL
Julian Hyde
 
Morel, a data-parallel programming language
Julian Hyde
 
Is there a perfect data-parallel programming language? (Experiments with More...
Julian Hyde
 
Morel, a Functional Query Language
Julian Hyde
 
Apache Calcite (a tutorial given at BOSS '21)
Julian Hyde
 
The evolution of Apache Calcite and its Community
Julian Hyde
 
What to expect when you're Incubating
Julian Hyde
 
Open Source SQL - beyond parsers: ZetaSQL and Apache Calcite
Julian Hyde
 
Efficient spatial queries on vanilla databases
Julian Hyde
 
Smarter Together - Bringing Relational Algebra, Powered by Apache Calcite, in...
Julian Hyde
 
Tactical data engineering
Julian Hyde
 
Don't optimize my queries, organize my data!
Julian Hyde
 
Spatial query on vanilla databases
Julian Hyde
 
Data all over the place! How SQL and Apache Calcite bring sanity to streaming...
Julian Hyde
 
Apache Calcite: A Foundational Framework for Optimized Query Processing Over ...
Julian Hyde
 
Lazy beats Smart and Fast
Julian Hyde
 
Don’t optimize my queries, optimize my data!
Julian Hyde
 
Data profiling with Apache Calcite
Julian Hyde
 
A smarter Pig: Building a SQL interface to Apache Pig using Apache Calcite
Julian Hyde
 
Data Profiling in Apache Calcite
Julian Hyde
 
Streaming SQL
Julian Hyde
 
Ad

Recently uploaded (20)

PPT
FALLSEM2025-26_ISWE304L_TH_VL2025260102786_2025-07-10_Reference-Material-II.ppt
AKSHAYA255427
 
PDF
Why Should Businesses Extract Cuisine Types Data from Multiple U.S. Food Apps...
devilbrown689
 
PPTX
Audio Editing and it's techniques in computer graphics.pptx
fosterbayirinia3
 
DOCX
The Future of Smart Factories Why Embedded Analytics Leads the Way
Varsha Nayak
 
PDF
A REACT POMODORO TIMER WEB APPLICATION.pdf
Michael624841
 
PDF
The Role of Automation and AI in EHS Management for Data Centers.pdf
TECH EHS Solution
 
PDF
Winning Business in a Slowing Economy, How CPQ helps Manufacturers Protect Ma...
systemscincom
 
PPTX
10 Hidden App Development Costs That Can Sink Your Startup.pptx
Lunar Web Solution
 
PDF
Why Use Open Source Reporting Tools for Business Intelligence.pdf
Varsha Nayak
 
PPTX
Benefits of DCCM for Genesys Contact Center
pointel ivr
 
PDF
Build Multi-agent using Agent Development Kit
FadyIbrahim23
 
PPTX
Save Business Costs with CRM Software for Insurance Agents
Insurance Tech Services
 
PDF
Community & News Update Q2 Meet Up 2025
VictoriaMetrics
 
PPTX
Materi_Pemrograman_Komputer-Looping.pptx
RanuFajar1
 
PDF
ShowUs: Pharo Stream Deck (ESUG 2025, Gdansk)
ESUG
 
PDF
Rise With SAP partner in Mumbai.........
pts464036
 
PPTX
Services offered by Dynamic Solutions in Pakistan
DaniyaalAdeemShibli1
 
PPT
Overview of Oracle Receivables Process.ppt
nbvreddy229
 
PDF
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
Hironori Washizaki
 
PPTX
Why Use Open Source Reporting Tools for Business Intelligence.pptx
Varsha Nayak
 
FALLSEM2025-26_ISWE304L_TH_VL2025260102786_2025-07-10_Reference-Material-II.ppt
AKSHAYA255427
 
Why Should Businesses Extract Cuisine Types Data from Multiple U.S. Food Apps...
devilbrown689
 
Audio Editing and it's techniques in computer graphics.pptx
fosterbayirinia3
 
The Future of Smart Factories Why Embedded Analytics Leads the Way
Varsha Nayak
 
A REACT POMODORO TIMER WEB APPLICATION.pdf
Michael624841
 
The Role of Automation and AI in EHS Management for Data Centers.pdf
TECH EHS Solution
 
Winning Business in a Slowing Economy, How CPQ helps Manufacturers Protect Ma...
systemscincom
 
10 Hidden App Development Costs That Can Sink Your Startup.pptx
Lunar Web Solution
 
Why Use Open Source Reporting Tools for Business Intelligence.pdf
Varsha Nayak
 
Benefits of DCCM for Genesys Contact Center
pointel ivr
 
Build Multi-agent using Agent Development Kit
FadyIbrahim23
 
Save Business Costs with CRM Software for Insurance Agents
Insurance Tech Services
 
Community & News Update Q2 Meet Up 2025
VictoriaMetrics
 
Materi_Pemrograman_Komputer-Looping.pptx
RanuFajar1
 
ShowUs: Pharo Stream Deck (ESUG 2025, Gdansk)
ESUG
 
Rise With SAP partner in Mumbai.........
pts464036
 
Services offered by Dynamic Solutions in Pakistan
DaniyaalAdeemShibli1
 
Overview of Oracle Receivables Process.ppt
nbvreddy229
 
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
Hironori Washizaki
 
Why Use Open Source Reporting Tools for Business Intelligence.pptx
Varsha Nayak
 

Cubing and Metrics in SQL, oh my!

  • 1. Cubing and Metrics in SQL, oh my! Julian Hyde (Google) Data Council • Austin, TX • 2023-03-29
  • 2. SQL vs BI BI tools implement their own languages on top of SQL. Why not SQL? Possible reasons: ● Semantic Model ● Control presentation / visualization ● Governance ● Pre-join tables ● Define reusable calculations ● Ask complex questions in a concise way
  • 3. Processing BI in SQL Why we should do it ● Move processing, not data ● Cloud SQL scale ● Remove data lag ● SQL is open Why it’s hard ● Different paradigm ● More complex data model ● Can’t break SQL
  • 4. What’s this talk about? Extensions to Apache Calcite’s SQL dialect Adoption by other SQL engines? Rethinking the “semantic model” and “metrics layer” An API for data?
  • 5. Pasta machine vs Pizza delivery
  • 6. Relational algebra (bottom-up) Multidimensional (top-down) Products Suppliers ⨝ ⨝ Σ ⨝ σ Sales Products Suppliers ⨝ ⨝ Σ σ Sales π (Supplier: ‘ACE’, Date: 2022-01’, Product: all) (Supplier: ‘ACE’, Date: 2023-01’, Product: all) Supplier Product Date Bottom-up vs Top-down query
  • 7. A multidimensional query #1 Select top 5 suppliers for each product category for last year, based on total sales.
  • 8. A multidimensional query #2 For each product category, select total sales this month of the product that had highest sales in that category last month.
  • 9. A multidimensional query #3 For supplier “Ace” and for each product, give the fractional increase in the sales in January 2023 relative to the sales in January 2022.
  • 10. Query: ● For supplier “Ace” and for each product, give the fractional increase in the sales in January 2023 relative to the sales in January 2022. SQL MDX SELECT p.prodId, s95.sales, (s95.sales - s94.sales) / s95.sales FROM ( SELECT p.prodId, SUM(s.sales) AS sales FROM Sales AS s JOIN Suppliers AS u USING (suppId) JOIN Products AS p USING (prodId) WHERE u.name = ‘ACE’ AND FLOOR(s.date TO MONTH) = ‘2023-01-01’ GROUP BY p.prodId) AS s95 LEFT JOIN ( SELECT p.prodId, SUM(s.sales) AS sales FROM Sales AS s JOIN Suppliers AS u USING (suppId) JOIN Products AS p USING (prodId) WHERE u.name = ‘ACE’ AND FLOOR(s.date TO MONTH) = ‘2022-01-01’ GROUP BY p.prodId) AS s94 USING (prodId) WITH MEMBER [Measures].[Sales Last Year] = ([Measures].[Sales], ParallelPeriod([Date], 1, [Date].[Year])) MEMBER [Measures].[Sales Growth] = ([Measures].[Sales] - [Measures].[Sales Last Year]) / [Measures].[Sales Last Year] SELECT [Measures].[Sales Growth] ON COLUMNS, [Product].Members ON ROWS FROM [Sales] WHERE ([Supplier].[ACE], [Date].[1995].[Jan])
  • 11. Query: ● For supplier “Ace” and for each product, give the fractional increase in the sales in January 2023 relative to the sales in January 2022. SQL SQL with measures SELECT p.prodId, s95.sales, (s95.sales - s94.sales) / s95.sales FROM ( SELECT p.prodId, SUM(s.sales) AS sales FROM Sales AS s JOIN Suppliers AS u USING (suppId) JOIN Products AS p USING (prodId) WHERE u.name = ‘ACE’ AND FLOOR(s.date TO MONTH) = ‘2023-01-01’ GROUP BY p.prodId) AS s95 LEFT JOIN ( SELECT p.prodId, SUM(s.sales) AS sales FROM Sales AS s JOIN Suppliers AS u USING (suppId) JOIN Products AS p USING (prodId) WHERE u.name = ‘ACE’ AND FLOOR(s.date TO MONTH) = ‘2022-01-01’ GROUP BY p.prodId) AS s94 USING (prodId) SELECT p.prodId, SUM(s.sales) AS MEASURE sumSales, sumSales AT (SET FLOOR(s.date TO MONTH) = ‘2022-01-01’) AS MEASURE sumSalesLastYear FROM Sales AS s JOIN Suppliers AS u USING (suppId) JOIN Products AS p USING (prodId)) WHERE u.name = ‘ACE’ AND FLOOR(s.date TO MONTH) = ‘2023-01-01’ GROUP BY p.prodId
  • 12. Self-joins, correlated subqueries, window aggregates, measures Window aggregate functions were introduced to save on self-joins. Some DBs rewrite scalar subqueries and self-joins to window aggregates [Zuzarte2003]. Window aggregates are more concise, easier to optimize, and often more efficient. However, window aggregates can only see data that is from the same table, and is allowed by the WHERE clause. Measures overcome that limitation. SELECT * FROM Employees AS e WHERE sal > ( SELECT AVG(sal) FROM Employees WHERE deptno = e.deptno) SELECT * FROM Employees AS e WHERE sal > AVG(sal) OVER (PARTITION BY deptno)
  • 13. A measure is… … a column with an aggregate function. SUM(sales) … a column that, when used as an expression, knows how to aggregate itself. (SUM(sales) - SUM(cost)) / SUM(sales) … a column that, when used as expression, can evaluate itself in any context. Its value depends on, and only on, the predicate placed on its dimensions. (SELECT SUM(forecastSales) FROM SalesForecast AS s WHERE predicate(s)) ExchService$ClosingRate( ‘USD’, ‘EUR’, sales.date)
  • 14. SELECT MOD(deptno, 2) = 0 AS evenDeptno, avgSal2 FROM WHERE deptno < 30 SELECT deptno, AVG(avgSal) AS avgSal2 FROM GROUP BY deptno Table model Tables are SQL’s fundamental model. The model is closed – queries consume and produce tables. Tables are opaque – you can’t deduce the type, structure or private data of a table. SELECT deptno, job, AVG(sal) AS avgSal FROM Employees GROUP BY deptno, job
  • 15. SELECT e.deptno, e.job, d.dname, e.avgSal / e.deptAvgSal FROM AS e JOIN Departments AS d USING (deptno) WHERE d.dname <> ‘MARKETING’ GROUP BY deptno, job We propose to allow any table and query to have measure columns. The model is closed – queries consume and produce tables-with-measures. Tables-with-measures are semi-opaque – you can’t deduce the type, structure or private data, but you can evaluate the measure in any context that can be expressed as a predicate on the measure’s dimensions. SELECT *, avgSal AS MEASURE avgSal, avgSal AT (CLEAR deptno) AS MEASURE deptAvgSal FROM Table model with measures SELECT *, AVG(sal) AS MEASURE avgSal FROM Employees
  • 16. Model + Query + Engine = Data system Query language Data model Engine
  • 17. Syntax expression AS MEASURE name – defines a measure in the SELECT clause AGGREGATE(measure) – evaluates a measure in a GROUP BY query expression AT (contextModifier…) – evaluates expression in a modified context contextModifier ::= CLEAR dimension [, dimension… ] | CLEAR ALL [ EXCEPT dimension [, dimension… ] ] | SET dimension = [CURRENT] expression | VISIBLE | ALL aggFunction(aggFunction(expression) PER dimension) – multi-level aggregation
  • 18. Plan of attack 1. Add measures to the table model, and allow queries to use them ◆ Measures are defined only via the Table API 2. Define measures using SQL expressions (AS MEASURE) ◆ You can still define them using the Table API 3. Context-sensitive expressions (AT)
  • 19. Semantics 0. We have a measure M, value type V, in a table T. CREATE VIEW AnalyticEmployees AS SELECT *, AVG(sal) AS MEASURE avgSal FROM Employees 1. System defines a row type R with the non-measure columns. CREATE TYPE R AS ROW (deptno: INTEGER, job: VARCHAR) 2. System defines an auxiliary function for M. (Function is typically a scalar subquery that references the measure’s underlying table.) CREATE FUNCTION computeAvgSal( rowPredicate: FUNCTION<R, BOOLEAN>) = (SELECT AVG(e.sal) FROM Employees AS e WHERE APPLY(rowPredicate, e))
  • 20. Semantics (continued) 3. We have a query that uses M. SELECT deptno, avgSal / avgSal AT (CLEAR deptno) FROM AnalyticEmployees AS e GROUP BY deptno 4. Substitute measure references with calls to the auxiliary function with the appropriate predicate SELECT deptno, computeAvgSal(r → (r.deptno = e.deptno)) / computeAvgSal(r → TRUE)) FROM AnalyticEmployees AS e GROUP BY deptno 5. Planner inlines computeAvgSal and scalar subqueries SELECT deptno, AVG(sal) / MIN(avgSal) FROM ( SELECT deptno, sal, AVG(sal) OVER () AS avgSal FROM Employees) GROUP BY deptno
  • 21. Calculating at the right grain Example Formula Grain Computing the revenue from units and unit price units * pricePerUnit AS revenue Row Sum of revenue (additive) SUM(revenue) AS MEASURE sumRevenue Top Profit margin (non-additive) (SUM(revenue) - SUM(cost)) / SUM(revenue) AS MEASURE profitMargin Top Inventory (semi-additive) SUM(LAST_VALUE(unitsInStock) PER inventoryDate) AS MEASURE sumInventory Intermediate Daily average (weighted average) AVG(sumRevenue PER orderDate) AS MEASURE dailyAvgRevenue Intermediate
  • 22. Subtotals & visible SELECT deptno, job, SUM(sal), sumSal FROM ( SELECT *, SUM(sal) AS MEASURE sumSal FROM Employees) WHERE job <> ‘ANALYST’ GROUP BY ROLLUP(deptno, job) ORDER BY 1,2 deptno job SUM(sal) sumSal 10 CLERK 1,300 1,300 10 MANAGER 2,450 2,450 10 PRESIDENT 5,000 5,000 10 8,750 8,750 20 CLERK 1,900 1,900 20 MANAGER 2,975 2,975 20 4,875 10,875 30 CLERK 950 950 30 MANAGER 2,850 2,850 30 SALES 5,600 5,600 30 9,400 9,400 20,750 29,025 Measures by default sum ALL rows; Aggregate functions sum only VISIBLE rows
  • 23. Visible Expression Example Which rows? Aggregate function SUM(sal) Visible only Measure sumSal All AGGREGATE applied to measure AGGREGATE(sumSal) Visible only Measure with VISIBLE sumSal AT (VISIBLE) Visible only Measure with ALL sumSal AT (ALL) All
  • 24. Measures don’t require GROUP BY Evaluating a measure on each row SELECT deptno, avgSal FROM AnalyticEmployees AS e Evaluating a measure on a window of several rows SELECT deptno, avgSal OVER (PARTITION BY job ORDER BY hiredate RANGE ‘1’ YEAR PRECEDING) FROM AnalyticEmployees AS e
  • 25. Semantic models versus databases In my opinion, a semantic model… ● … is the place to share data and calculations ● … needs a really good query language ○ (So you don’t have to change the model every time someone has a new question) ● … doesn’t become a database just because it speaks SQL ● … should do other things too ○ (Access control, governance, presentation defaults, guide data exploration, transform data, tune data, …) Shouldn’t the semantic model be outside the database? (I don’t want to be tied to one DBMS vendor.) I have a great semantic model already. Why do I need a query language? My users don’t want to write SQL. What even is a semantic model?
  • 26. Summary Top-down evaluation makes queries concise Measures make calculations reusable Measures don’t break SQL
  • 27. References Papers ● [Agrawal1997] “Modeling multidimensional databases” (Agrawal, Gupta, and Sarawagi, 1997) ● [Zuzarte2003] “WinMagic: Subquery Elimination Using Window Aggregation” (Zuzarte, Pirahash, Ma, Cheng, Liu, and Wong, 2003) Issues ● [CALCITE-4488] WITHIN DISTINCT clause for aggregate functions (experimental) ● [CALCITE-4496] Measure columns ("SELECT ... AS MEASURE") ● [CALCITE-5105] Add MEASURE type and AGGREGATE aggregate function ● [CALCITE-5155] Custom time frames ● [CALCITE-xxxx] PER ● [CALCITE-xxxx] AT
  • 30. Abstract If SQL is the universal language of data, why do we author our most important data applications (metrics, analytics, business intelligence) in languages other than SQL? Multidimensional databases and languages such as MDX, DAX and Tableau LOD solve these problems but introduce others: they require specialized knowledge, complicate the data pipeline and don’t integrate well. Is it possible to define and query business intelligence models in SQL? Apache Calcite has extended SQL to support metrics (which we call ‘measures’), filter context, and analytic expressions. With these concepts you can define data models (which we call Analytic Views) that contain metrics, use them in queries, and define new metrics in queries. In this talk by the original developer of Apache Calcite, we describe the SQL syntax extensions for metrics, and how to use them for cross-dimensional calculations such as period-over-period, percent-of-total, non-additive and semi-additive measures. We describe how we got around fundamental limitations in SQL semantics, and approaches for optimizing queries that use metrics. ABOUT THE SPEAKER Julian Hyde is the original developer of Apache Calcite, an open source framework for building data management systems, and Morel, a functional query language. Previously he created Mondrian, an analytics engine, and SQLstream, an engine for continuous queries. He is a staff engineer at Google, where he works on Looker and BigQuery.
  • 31. Some multidimensional queries ● Give the total sales for each product in each quarter of 1995. (Note that quarter is a function of date). ● For supplier “Ace” and for each product, give the fractional increase in the sales in January 1995 relative to the sales in January 1994. ● For each product give its market share in its category today minus its market share in its category in October 1994. ● Select top 5 suppliers for each product category for last year, based on total sales. ● For each product category, select total sales this month of the product that had highest sales in that category last month. ● Select suppliers that currently sell the highest selling product of last month. ● Select suppliers for which the total sale of every product increased in each of last 5 years. ● Select suppliers for which the total sale of every product category increased in each of last 5 years. From [Agrawal1997]. Assumes a database with dimensions {supplier, date, product} and measure {sales}.)