%sql
USE SCHEMA dbx_course;
SELECT status, count(*) AS orders FROM orders GROUP BY status ORDER BY orders DESC
Module 13: Databricks SQL & Analytics
SQL warehouses, advanced SQL, AI/BI dashboards and Genie.
Topics in this module
Query the lakehouse with SQL, then serve the results to people. SQL warehouses run the queries. Dashboards, Genie and BI tools sit on top.
- Uses the practice tables
orders,customers,products(Module 4). Topic 12 also usesgold_daily_revenue(Module 8) - Run the SQL cells in a SQL editor or in a notebook with
%sql - Free Edition: one SQL warehouse, size 2X-Small
Databricks SQL Architecture
By the end: place Databricks SQL in the platform.
- Databricks SQL = the SQL-first experience: editor, warehouses, dashboards, alerts, query history
- Same Delta tables and Unity Catalog permissions as notebooks and jobs
- Also reachable from outside: BI tools and drivers connect to a warehouse (topic 11)
| Part | Does |
|---|---|
| SQL editor | Write, save, share queries |
| SQL warehouse | Compute that runs them |
| AI/BI dashboards | Visual reports |
| Genie | Questions in plain language |
| Alerts | Notify when a query result crosses a rule |
| Query history | Every query, with its profile |
SQL Warehouses
By the end: look at your SQL warehouse and learn its settings.
Open it: sidebar SQL Warehouses (or Compute → SQL warehouses).
| Setting | Meaning |
|---|---|
| Cluster size | T-shirt size (2X-Small is the smallest). Bigger = more power per query |
| Auto stop | Minutes idle before it stops: saves quota |
| Scaling | Min and max clusters, for many concurrent users |
| Type | Serverless, Pro or Classic |
- Free Edition: one warehouse, 2X-Small (fixed)
- A stopped warehouse starts when a query, dashboard or connection needs it
- Sizing rule: if a query spills to disk (see the profile), go one size up. More clusters help concurrency, not a single slow query
- Up to 1,000 queries can wait in the queue
%sql
SELECT current_catalog(), current_schema(), current_user(), version()
Keep auto stop short
Warehouses cost (or use quota) only while running. Short auto stop on small warehouses is the default for a reason.
Serverless SQL Warehouses
By the end: explain why serverless is the default choice for SQL warehouses.
| Feature | Serverless | Pro | Classic |
|---|---|---|---|
| Photon | Yes | Yes | Yes |
| Predictive I/O | Yes | Yes | No |
| Intelligent Workload Management | Yes | No | No |
| Typical start | 2–6 s | ~4 min | ~4 min |
- Intelligent Workload Management predicts each query's needs, queues when busy, and scales clusters up and down
- Databricks recommends serverless for most workloads
- Use Pro when serverless isn't available in your region or you need custom networking
Remember
Free Edition gives you serverless. Everything you learn here applies to the paid kinds as well.
Advanced Databricks SQL Functions
By the end: use SQL features that save you subqueries and loops.
QUALIFY filters on a window function:
%sql
-- latest order per customer
SELECT customer_id, order_id, order_ts
FROM orders
QUALIFY row_number() OVER (PARTITION BY customer_id ORDER BY order_ts DESC) = 1
FILTER, PIVOT and MAX_BY:
%sql
SELECT customer_id,
count(*) AS orders,
count(*) FILTER (WHERE status = 'cancelled') AS cancelled,
max_by(order_id, order_ts) AS last_order_id
FROM orders GROUP BY customer_id LIMIT 5
%sql
SELECT * FROM (SELECT product_id, status FROM orders)
PIVOT (count(*) FOR status IN ('completed', 'shipped', 'cancelled', 'returned'))
ORDER BY product_id LIMIT 5
Semi-structured and arrays:
%sql
SELECT '{"a": {"b": 5}, "tags": ["x", "y"]}':a.b::int AS b,
transform(array(1, 2, 3), x -> x * 10) AS tens,
filter(array(1, 2, 3, 4), x -> x % 2 = 0) AS evens
| Feature | Use |
|---|---|
QUALIFY |
Filter window results |
GROUP BY ROLLUP / CUBE |
Subtotals |
try_cast, try_divide |
Errors become NULL (ANSI is on) |
: path on JSON, VARIANT |
Query JSON without parsing columns |
transform, filter, aggregate, exists |
Work on arrays with lambdas |
IDENTIFIER(:name) |
Parameterised table and column names |
Views and Materialized Views
By the end: create views and materialized views and know the difference.
%sql
CREATE OR REPLACE VIEW completed_orders AS
SELECT * FROM orders WHERE status = 'completed';
SELECT count(*) FROM completed_orders
%sql
CREATE MATERIALIZED VIEW revenue_by_category AS
SELECT p.category, round(sum(o.quantity * p.unit_price), 2) AS revenue
FROM orders o JOIN products p USING (product_id)
WHERE o.status IN ('completed', 'shipped')
GROUP BY p.category
%sql
REFRESH MATERIALIZED VIEW revenue_by_category
| View | Materialized view | |
|---|---|---|
| Stores results | No: runs the query each time | Yes |
| Fresh | Always | As of the last refresh |
| Cost | On every read | On refresh (incremental when possible) |
| Use for | Reuse, abstraction, security | Heavy aggregates that many users read |
- A materialized view is managed by a pipeline behind the scenes. It needs Unity Catalog and a serverless (or Pro) warehouse
- Dynamic views and row filters / column masks limit what each user sees (Module 6)
- Metric views define business measures once in Unity Catalog so dashboards, Genie and BI tools all agree on "revenue"
Materialized views on Free Edition
Creating one starts a serverless pipeline. If it is refused, you are at the pipeline limit (Module 9), or it's not offered: use a table you rebuild in a job.
Query History and Query Profiles
By the end: find your queries in history and open a query profile.
Open it: Query History in the sidebar.
| Column / filter | Use |
|---|---|
| Status, duration, user | Find slow and failed queries |
| Time range, warehouse | Narrow to an incident |
| See query profile | Open the plan and metrics for one query |
In the profile (Module 12.15): top operators, rows, time, files pruned, bytes read, spill.
- Workflow for a slow query: history → profile → worst operator → fix → rerun → compare
- Queries answered from the result cache have no profile
- Notebook cells on serverless: See performance under the cell
- You see your own queries. Others need
CAN MONITORon the warehouse - The warehouse monitoring tab shows peak queued queries: above 0 means more capacity is needed
SQL Query Optimization
By the end: write SQL that the optimizer can do something with.
| Habit | Why |
|---|---|
Select the columns you need, not SELECT * |
Column pruning, less I/O |
| Filter on the raw column, not a function of it | Allows file pruning |
| Filter early, aggregate before joining | Smaller shuffles |
LIMIT while exploring |
Saves time and quota |
| Join on matching types | No casts that block pushdown |
| Pre-aggregate with a materialized view | Many readers, one computation |
approx_count_distinct |
Cheaper when exact isn't required |
%sql
-- check the plan before running something big
EXPLAIN FORMATTED
SELECT c.country, sum(o.quantity) AS qty
FROM orders o JOIN customers c USING (customer_id)
WHERE o.order_ts >= '2025-03-01'
GROUP BY c.country
- Layout does more than clever SQL: liquid clustering on filter columns, no tiny files (Module 12)
EXPLAINdoesn't run the query; the profile shows what actually happened- Statistics keep the optimizer honest: keep predictive optimization on for managed tables
Measure, then rewrite
A query that looks wasteful may be fine. Read the profile before changing it.
Result and Disk Caching
By the end: know the caches that speed up repeated queries.
- Query result cache: an identical query on unchanged data returns the stored result
- Disk (data) cache: Delta/Parquet files read often stay on fast local storage
- Results are invalidated when the underlying tables change
- To test real speed, change the query slightly (for example
LIMIT) or look at a first run - Nothing to configure: don't use
CACHE TABLEas a habit
Benchmark honestly
A second run is often faster only because of caches. Compare cold runs to cold runs.
AI/BI Dashboards
By the end: build and publish an AI/BI dashboard.
- Dashboards → Create dashboard
- Data tab → add a dataset with a query:
SELECT date(order_ts) AS order_date, status, count(*) AS orders,
round(sum(quantity * unit_price), 2) AS revenue
FROM dbx_course.orders JOIN dbx_course.products USING (product_id)
GROUP BY ALL
- Canvas tab → Add a visualization: line chart of revenue by
order_date; bar chart of orders bystatus; a counter for total revenue - Add a filter widget on
status - Publish; set who can view and which credentials the data uses
| Feature | Use |
|---|---|
| Datasets | The SQL behind charts. Reuse one for many charts |
| Parameters and filters | Let viewers change what they see |
| Cross-filtering | Click a bar to filter the others |
| Schedule and subscriptions | Refresh and email on a schedule |
| Draft vs published | Edit safely, then publish |
- Put business logic in gold tables or views, not inside dashboard SQL
- Fewer, well-named datasets beat one query per chart
Dashboards read gold
Keep the heavy transformation in the pipeline, so a dashboard is only "select and chart".
Genie and Natural Language Analytics
By the end: set up a Genie agent so people can ask questions in plain language.
- Genie answers questions about your tables in natural language and shows the SQL it wrote
- You set up a Genie agent (earlier called a Genie space) around a few tables
Set it up:
- Genie → New, pick tables:
orders,customers,products - Add instructions: "Revenue counts statuses completed and shipped only"
- Add example SQL for typical questions
- Test with: "Which category had the most revenue?"
| Quality lever | Effect |
|---|---|
| Good column comments and table descriptions | Genie reads them |
| Instructions on business rules | Consistent definitions |
| Example queries and verified answers | Reliable answers for common questions |
| Few, focused tables | Fewer wrong joins |
- Answers use the asking user's permissions (Unity Catalog applies)
- Always read the generated SQL for important numbers
- Genie runs on a SQL warehouse
Check Free Edition
Genie availability and limits depend on your workspace. Usage by people is currently free in the docs, but check the Genie page for what is included.
BI Tool Integration
By the end: connect BI tools and Python to a SQL warehouse.
| You need | Where |
|---|---|
| Server hostname, HTTP path | Warehouse → Connection details |
| Authentication | OAuth (preferred), or a personal access token |
| Partner Connect | One-click setup for Hex, Power BI, Tableau, Sigma, ThoughtSpot |
# Python SQL connector (pip install databricks-sql-connector)
from databricks import sql
with sql.connect(server_hostname="<host>", http_path="<http-path>", access_token="<token>") as conn:
with conn.cursor() as cur:
cur.execute("SELECT status, count(*) FROM dbx_course.orders GROUP BY status")
print(cur.fetchall())
- Keep tokens in a secret store, not in code. Prefer OAuth or a service principal in production
- BI tools respect Unity Catalog permissions, row filters and column masks
- Point tools at gold tables, views or metric views
Free Edition
Whether you can create a token or connect from outside is not confirmed in the docs. Look under Settings → Developer. This topic may be reference only.
Serving Gold-Layer Data
By the end: publish gold-layer data so others can use it safely.
%sql
-- a stable, documented serving view over gold
CREATE OR REPLACE VIEW serving_daily_revenue
COMMENT 'Daily revenue for completed and shipped orders. Owner: data-eng'
AS SELECT order_date, orders, revenue FROM gold_daily_revenue;
GRANT SELECT ON VIEW serving_daily_revenue TO `account users`
| Practice | Why |
|---|---|
| Serve gold, not bronze or silver | Clean, agreed definitions |
| Name and comment tables and columns | People (and Genie) can understand them |
Grant to groups, SELECT only |
Least privilege (Module 6) |
| Keep schema stable; add columns, don't rename | Consumers keep working |
| Row filters / masks for sensitive data | Same table, different views per user |
| One source of metric definitions | Dashboards and Genie agree |
- Share outside Databricks with Delta Sharing (Module 6.12)
- Freshness: say how often a table refreshes, and alert if it doesn't
GRANT to account users
Fine for a practice schema. In real workspaces, grant to specific groups.
What you can do now
- Databricks SQL, warehouses and why serverless
- Advanced SQL, views and materialized views
- Query history, the profile, optimization and caches
- Dashboards, Genie, BI connections and serving gold data