From ae00734ccca967a1821d027e0c31af9a2a285bea Mon Sep 17 00:00:00 2001 From: Chris Eubank <108756251+christianeu-db@users.noreply.github.com> Date: Thu, 27 Aug 2026 22:01:08 +0000 Subject: [PATCH 1/2] Add BI SQL examples capturing tool-generated metric queries Add bi-sql-examples/ with real SQL that BI tools generate when they query metrics defined outside the tool. Include a tableau/ subfolder with a setup.sql model sketch, a README, and four feature-area examples: top-N filters, LOD two-stage aggregation, sets, and multi-table joins and relationships. These query shapes help verify that Ossie can cover the complex cases BI tools produce. --- bi-sql-examples/README.md | 18 ++ bi-sql-examples/tableau/01-top-n-filters.sql | 101 +++++++++++ .../tableau/02-lod-two-stage-aggregation.sql | 42 +++++ bi-sql-examples/tableau/03-sets.sql | 66 +++++++ .../04-multi-table-joins-relationships.sql | 161 ++++++++++++++++++ bi-sql-examples/tableau/README.md | 23 +++ bi-sql-examples/tableau/setup.sql | 58 +++++++ 7 files changed, 469 insertions(+) create mode 100644 bi-sql-examples/README.md create mode 100644 bi-sql-examples/tableau/01-top-n-filters.sql create mode 100644 bi-sql-examples/tableau/02-lod-two-stage-aggregation.sql create mode 100644 bi-sql-examples/tableau/03-sets.sql create mode 100644 bi-sql-examples/tableau/04-multi-table-joins-relationships.sql create mode 100644 bi-sql-examples/tableau/README.md create mode 100644 bi-sql-examples/tableau/setup.sql diff --git a/bi-sql-examples/README.md b/bi-sql-examples/README.md new file mode 100644 index 00000000..28cb837f --- /dev/null +++ b/bi-sql-examples/README.md @@ -0,0 +1,18 @@ +BI SQL examples +=============== + +Real SQL that BI tools generate when they query, via SQL, metrics defined outside +the tool. The +goal is to study these query shapes to ensure that Ossie can fully and safely +cover the complex cases BI tools produce. + +The examples read measures with the `MEASURE()` function, but that is only for +illustration: any proposal will require the BI tool to have some function for +querying measures. + +Layout +------ + +One subfolder per BI tool. Each subfolder holds a `setup.sql` that shows the +shape of the tables and metrics, one `.sql` file per feature area, and a +`README.md`. diff --git a/bi-sql-examples/tableau/01-top-n-filters.sql b/bi-sql-examples/tableau/01-top-n-filters.sql new file mode 100644 index 00000000..51790901 --- /dev/null +++ b/bi-sql-examples/tableau/01-top-n-filters.sql @@ -0,0 +1,101 @@ +-- ============================================================================ +-- Tableau BI SQL examples: Top N filters +-- +-- Shows how Tableau's low-code filter UI turns into SQL, from a plain aggregate +-- up to a top-N filter that needs a join and subquery. The last query shows an +-- optimization Tableau applies when the filter dimension matches the +-- visualization dimension. +-- +-- Tableau feature: Filter Data from Your Views (the "Top" tab). +-- https://help.tableau.com/current/pro/desktop/en-us/filtering.htm +-- ============================================================================ + +-- ---------------------------------------------------------------------------- +-- Query 1: simple aggregation. +-- Visualize Category by the Total Quantity measure. A plain aggregate that +-- calls the MEASURE function. +-- ---------------------------------------------------------------------------- +SELECT + `orders_metrics`.`category` AS `category`, + (MEASURE(`orders_metrics`.`total_quantity`)) AS `total_quantity` +FROM + `orders_metrics` `orders_metrics` +GROUP BY + 1; + +-- ---------------------------------------------------------------------------- +-- Query 2: simple WHERE filter. +-- A low-code date-range filter (years 2023 and 2024) becomes a plain WHERE. +-- Filters expressible as a simple WHERE clause tend to port across BI vendors. +-- ---------------------------------------------------------------------------- +SELECT + `orders_metrics`.`category` AS `category`, + (MEASURE(`orders_metrics`.`total_quantity`)) AS `total_quantity` +FROM + `orders_metrics` `orders_metrics` +WHERE + (YEAR(`orders_metrics`.`order_date`) IN (2023, 2024)) +GROUP BY + 1; + +-- ---------------------------------------------------------------------------- +-- Query 3: top-N filter on a different dimension (join + subquery). +-- Keep the top 2 states by Total Revenue while visualizing Category by Total +-- Quantity. A subquery ranks states by the revenue measure; the main query +-- joins to it to apply the filter before aggregating. +-- ---------------------------------------------------------------------------- +SELECT + `orders_metrics`.`category` AS `category`, + (MEASURE(`orders_metrics`.`total_quantity`)) AS `total_quantity` +FROM + `orders_metrics` `orders_metrics` + JOIN ( + SELECT + `orders_metrics`.`state_id` AS `state_id`, + (MEASURE(`orders_metrics`.`total_revenue`)) AS `x__alias__0` + FROM + `orders_metrics` `orders_metrics` + GROUP BY + 1 + ORDER BY + `x__alias__0` DESC, + `state_id` ASC + LIMIT 2 + ) `t0` + ON (`orders_metrics`.`state_id` = `t0`.`state_id`) +GROUP BY + 1; + +-- ---------------------------------------------------------------------------- +-- Query 4: top-N filter on the same dimension (folded). +-- Keep the top 2 categories by Total Revenue while visualizing Category. Because +-- the filter dimension equals the visualization dimension, Tableau folds the +-- filter subquery into the main query - no join needed. +-- +-- Note: this fold corresponds to Query 3's join-and-subquery technique, not to +-- its specific result (Query 3 filters top-2 states; this filters top-2 +-- categories). The fold is valid only under the stable-domain assumption: that a +-- dimension's domain is fixed regardless of the other measures and dimensions in +-- the query. +-- +-- Separately, Query 3 joins the top-N subquery with an equality predicate +-- (state_id = t0.state_id), not IS NOT DISTINCT FROM. That matches a null-safe +-- join only when state_id has no NULLs. This is a distinct assumption from the +-- fold's: the fold relies on a stable domain, while this plain-= join relies on +-- a NULL-free join key. +-- +-- Both optimizations are unsafe against multi-table models behind opaque +-- interfaces, where adding or removing a measure can change the dimension domain. +-- ---------------------------------------------------------------------------- +SELECT + `orders_metrics`.`category` AS `category`, + (MEASURE(`orders_metrics`.`total_quantity`)) AS `total_quantity`, + (MEASURE(`orders_metrics`.`total_revenue`)) AS `x__alias__0` +FROM + `orders_metrics` `orders_metrics` +GROUP BY + 1 +ORDER BY + `x__alias__0` DESC, + `category` ASC +LIMIT 2; diff --git a/bi-sql-examples/tableau/02-lod-two-stage-aggregation.sql b/bi-sql-examples/tableau/02-lod-two-stage-aggregation.sql new file mode 100644 index 00000000..fe4dadf5 --- /dev/null +++ b/bi-sql-examples/tableau/02-lod-two-stage-aggregation.sql @@ -0,0 +1,42 @@ +-- ============================================================================ +-- Tableau BI SQL examples: LoDs for two-stage aggregation +-- +-- Measures compose with Tableau's own FIXED level-of-detail (LoD) calculations. +-- This computes a measure at a per-state grain, then averages that result: for +-- each category, the average across its states of total revenue. +-- +-- The generated SQL is two-stage: an inner query computes the per-state measure +-- (MEASURE(total_revenue) grouped by state_id), and the outer query applies the +-- second aggregation (AVG) after joining on the state grain. The join uses +-- IS NOT DISTINCT FROM so NULL state_id values match. +-- +-- Tableau feature: FIXED Level of Detail Expressions. +-- https://help.tableau.com/current/pro/desktop/en-us/calculations_calculatedfields_lod_fixed.htm +-- ============================================================================ + +SELECT + `t0`.`category` AS `category`, + AVG(`t1`.`x_measure__1`) AS `average_of_total_revenues_by_state` +FROM + ( + SELECT + `orders_metrics`.`category` AS `category`, + `orders_metrics`.`state_id` AS `state_id` + FROM + `orders_metrics` `orders_metrics` + GROUP BY + 1, + 2 + ) `t0` + JOIN ( + SELECT + `orders_metrics`.`state_id` AS `state_id`, + (MEASURE(`orders_metrics`.`total_revenue`)) AS `x_measure__1` + FROM + `orders_metrics` `orders_metrics` + GROUP BY + 1 + ) `t1` + ON (`t0`.`state_id` IS NOT DISTINCT FROM `t1`.`state_id`) +GROUP BY + 1; diff --git a/bi-sql-examples/tableau/03-sets.sql b/bi-sql-examples/tableau/03-sets.sql new file mode 100644 index 00000000..00883883 --- /dev/null +++ b/bi-sql-examples/tableau/03-sets.sql @@ -0,0 +1,66 @@ +-- ============================================================================ +-- Tableau BI SQL examples: sets (LoD calculation vs. built-in Set feature) +-- +-- Two different low-code paths to the same result, producing different SQL. +-- Goal: graph Total Quantity split by high-revenue vs. low-revenue categories, +-- where a high-revenue category has Total Revenue >= 5000. +-- +-- Key takeaway: BI tools can generate very different SQL for similar user-facing +-- capabilities, so a SQL interface to reusable semantics must be robust across +-- query shapes. +-- +-- Tableau feature: Create Sets. +-- https://help.tableau.com/current/pro/desktop/en-us/sortgroup_sets_create.htm +-- ============================================================================ + +-- ---------------------------------------------------------------------------- +-- Query A: FIXED LoD calculation used as a dimension. +-- Tableau computes Total Revenue per category in a subquery, joins it back to +-- the main table (IS NOT DISTINCT FROM handles NULL categories), and derives +-- the split dimension by applying the >= 5000 comparison to the measure. +-- ---------------------------------------------------------------------------- +SELECT + (`t0`.`x_measure__0` >= 5000) AS `is_top_category`, + (MEASURE(`orders_metrics`.`total_quantity`)) AS `total_quantity` +FROM + `orders_metrics` `orders_metrics` + JOIN ( + SELECT + `orders_metrics`.`category` AS `category`, + (MEASURE(`orders_metrics`.`total_revenue`)) AS `x_measure__0` + FROM + `orders_metrics` `orders_metrics` + GROUP BY + 1 + ) `t0` + ON (`orders_metrics`.`category` IS NOT DISTINCT FROM `t0`.`category`) +GROUP BY + 1; + +-- ---------------------------------------------------------------------------- +-- Query B: the built-in Set feature (in/out membership). +-- Tableau computes the high-revenue categories in a subquery that filters with +-- HAVING and emits the category plus a constant flag column. The main table +-- LEFT JOINs that subquery (the left join keeps all rows) and derives set +-- membership by testing whether the flag is non-NULL. +-- ---------------------------------------------------------------------------- +SELECT + (NOT (`t0`.`xtemp1_output` IS NULL)) AS `io_high_revenue_categories`, + (MEASURE(`orders_metrics`.`total_quantity`)) AS `total_quantity` +FROM + `orders_metrics` `orders_metrics` + LEFT OUTER JOIN ( + SELECT + `orders_metrics`.`category` AS `category`, + 1 AS `xtemp1_output`, + (MEASURE(`orders_metrics`.`total_revenue`)) AS `x_measure__0` + FROM + `orders_metrics` `orders_metrics` + GROUP BY + 1 + HAVING + ((MEASURE(`orders_metrics`.`total_revenue`)) >= 5000.) + ) `t0` + ON (`orders_metrics`.`category` IS NOT DISTINCT FROM `t0`.`category`) +GROUP BY + 1; diff --git a/bi-sql-examples/tableau/04-multi-table-joins-relationships.sql b/bi-sql-examples/tableau/04-multi-table-joins-relationships.sql new file mode 100644 index 00000000..f7008c17 --- /dev/null +++ b/bi-sql-examples/tableau/04-multi-table-joins-relationships.sql @@ -0,0 +1,161 @@ +-- ============================================================================ +-- Tableau BI SQL examples: multi-table analysis (joins + relationships) +-- +-- A two-table model (tickets and sales), each with its own measures. Tableau +-- offers two ways to combine them: +-- * Low-code joins: the user forces an explicit join path and type. +-- * Relationships: Tableau issues a query per level of detail and picks the +-- join shape itself, allowing more flexible analysis. +-- +-- With native SQL measures, the SQL layer handles measure de-duplication after +-- the join (no double counting across a many-to-many join), while the BI tool +-- keeps control of the join path and type. +-- +-- Tableau feature: Relate Your Data (relationships). +-- https://help.tableau.com/current/pro/desktop/en-us/relate_tables.htm +-- ============================================================================ + +-- ---------------------------------------------------------------------------- +-- Query 1: low-code join, measures from both tables. +-- The user forces a many-to-many join on region. Region sales are plotted with +-- Ticket Count (a tickets measure) and Total Sales (a sales measure). Native +-- SQL measures avoid any measure duplication across the M:M join. +-- ---------------------------------------------------------------------------- +SELECT + `sales`.`region` AS `region_sales`, + (MEASURE(`tickets`.`ticket_count`)) AS `ticket_count`, + (MEASURE(`sales`.`total_sales`)) AS `total_sales` +FROM + `tickets` `tickets` + JOIN `sales` `sales` + ON (`tickets`.`region` = `sales`.`region`) +GROUP BY + 1; + +-- ---------------------------------------------------------------------------- +-- Query 2: de-duplication preserved when the join key is not a group-by field. +-- Same low-code join, but grouped by sale_id (a non-join-key dimension from the +-- other table). Measure de-duplication still holds: Ticket Count is not +-- inflated by the M:M join. +-- ---------------------------------------------------------------------------- +SELECT + `sales`.`sale_id` AS `sale_id`, + (MEASURE(`tickets`.`ticket_count`)) AS `ticket_count`, + (MEASURE(`sales`.`total_sales`)) AS `total_sales` +FROM + `tickets` `tickets` + JOIN `sales` `sales` + ON (`tickets`.`region` = `sales`.`region`) +GROUP BY + 1; + +-- ---------------------------------------------------------------------------- +-- Query 3: relationships, one query per level of detail (ticket count case). +-- Using the relationship feature, Tableau issues a separate query per measure +-- grain. This is the ticket-count query, which spans tables: it first computes +-- the distinct set of regions from sales, joins that back to tickets to avoid +-- row duplication, then applies the measure aggregation. +-- ---------------------------------------------------------------------------- +SELECT + `t0`.`region` AS `region`, + (MEASURE(`tickets`.`ticket_count`)) AS `ticket_count` +FROM + `tickets` `tickets` + LEFT OUTER JOIN ( + SELECT + `sales`.`region` AS `region` + FROM + `sales` `sales` + GROUP BY + 1 + ) `t0` + ON (`tickets`.`region` = `t0`.`region`) +GROUP BY + 1; + +-- ---------------------------------------------------------------------------- +-- Query 4: relationships with dimensions from both sides of the join. +-- Ticket Count by region (grouped on the tickets side) and sale_id (from sales). +-- Tableau computes the unique (region, sale_id) pairs and joins them back to +-- the main table to avoid measure duplication from the many-to-many join. +-- +-- This query is an example of a measure column (ticket_count) passing through a +-- derived table unevaluated: it is referenced inside the derived table `t0` +-- without being aggregated. +-- ---------------------------------------------------------------------------- +SELECT + `t2`.`region` AS `region`, + `t2`.`sale_id` AS `sale_id`, + (MEASURE(`t0`.`ticket_count`)) AS `ticket_count` +FROM + ( + SELECT + `tickets`.`region` AS `region`, + `tickets`.`ticket_count` AS `ticket_count`, + `tickets`.`region` AS `region__tickets_` + FROM + `tickets` `tickets` + ) `t0` + JOIN ( + SELECT + `t1`.`region__tickets_` AS `region__tickets_`, + MIN(`sales`.`region`) AS `region`, + `sales`.`sale_id` AS `sale_id` + FROM + ( + SELECT + `tickets`.`region` AS `region`, + `tickets`.`region` AS `region__tickets_` + FROM + `tickets` `tickets` + ) `t1` + LEFT OUTER JOIN `sales` `sales` + ON (`t1`.`region__tickets_` = `sales`.`region`) + GROUP BY + 1, + 3 + ) `t2` + ON (`t0`.`region__tickets_` IS NOT DISTINCT FROM `t2`.`region__tickets_`) +GROUP BY + 1, + 2; + +-- ---------------------------------------------------------------------------- +-- Query 5: the same cross-table analysis with a plain aggregate (MAX), for +-- contrast. +-- Tableau already applies a related optimization for ordinary aggregates such as +-- MAX. This query does the same cross-table analysis as Query 4 but emits a +-- simpler shape: it aggregates a dimension (MAX(ticket_id)) rather than passing a +-- measure column through a derived table unevaluated. Measure-type awareness +-- would let Tableau rely on the engine's measure de-duplication, so the M:M +-- join's duplicate rows do not inflate the measure, and simplify the Query 4 +-- shape similarly. +-- ---------------------------------------------------------------------------- +SELECT + `sales`.`region` AS `region`, + `sales`.`sale_id` AS `sale_id`, + MAX(`t0`.`ticket_id`) AS `max_ticket` +FROM + ( + SELECT + `tickets`.`region` AS `region`, + `tickets`.`ticket_id` AS `ticket_id`, + `tickets`.`region` AS `region__tickets_` + FROM + `tickets` `tickets` + ) `t0` + LEFT OUTER JOIN `sales` `sales` + ON (`t0`.`region__tickets_` = `sales`.`region`) +GROUP BY + 1, + 2; + +-- ---------------------------------------------------------------------------- +-- Note: constraint-driven rewrites. +-- Tableau also rewrites based on database-constraint metadata and user-asserted +-- metadata. Asserting many-to-one cardinality reduces the number of inner +-- subqueries Tableau inserts to avoid measure duplication; asserting "all +-- records match" on referential integrity lets Tableau lower left joins to +-- inner joins. The source doc illustrates these with the UI rather than a +-- distinct captured query, so no separate SQL is reproduced here. +-- ---------------------------------------------------------------------------- diff --git a/bi-sql-examples/tableau/README.md b/bi-sql-examples/tableau/README.md new file mode 100644 index 00000000..d7bbe9f6 --- /dev/null +++ b/bi-sql-examples/tableau/README.md @@ -0,0 +1,23 @@ +Tableau BI SQL examples +======================= + +Real SQL that [Tableau](https://www.tableau.com/) generated while querying metrics +defined outside the tool. The proof of concept ran against a development build of +Databricks Metric Views, but the approach should work with a SQL interface to Ossie. + +The queries in this folder are captured for their SQL shape. `setup.sql` shows the model +shape generally and is not runnable; the proof of concept used Databricks Metric +View DDL for the actual model. + +How the SQL was produced +------------------------ + +Tableau queried the model through its existing SQL generation pipeline, with two +workarounds because this Tableau build does not query these natively: + +- **Measures**: the POC used Tableau's + [RAWSQLAGG](https://help.tableau.com/current/pro/desktop/en-us/functions_functions_passthrough.htm) + functions so that it could invoke the measure function. Every measure is + evaluated on the engine side. +- **Multi-table models**: built by hand in Tableau using joins and + relationships. diff --git a/bi-sql-examples/tableau/setup.sql b/bi-sql-examples/tableau/setup.sql new file mode 100644 index 00000000..47bda4ab --- /dev/null +++ b/bi-sql-examples/tableau/setup.sql @@ -0,0 +1,58 @@ +-- ============================================================================ +-- Tableau BI SQL examples: setup +-- +-- This file is NOT meant to be run. It shows the shape of the tables and the +-- metrics the example queries assume. +-- +-- The measure-declaration syntax below is illustrative only - it is not real, +-- runnable SQL. The proof of concept used Databricks Metric View DDL; this file +-- is written generally to show the model shape, so the captured queries are +-- examples of SQL shape rather than something to run against this setup. +-- ============================================================================ + +-- ---------------------------------------------------------------------------- +-- Single-table model: orders_metrics over orders_table +-- ---------------------------------------------------------------------------- + +CREATE TABLE orders_table ( + order_id INT, + order_date DATE, + category STRING, + amount DECIMAL(10, 2), + quantity INT, + state_id INT +); + +CREATE OR REPLACE VIEW orders_metrics AS +SELECT + *, + SUM(amount) TO MEASURE total_revenue, + SUM(quantity) TO MEASURE total_quantity +FROM orders_table; + +-- ---------------------------------------------------------------------------- +-- Two-table model: sales and tickets +-- ---------------------------------------------------------------------------- + +CREATE TABLE sales_table ( + sale_id INT, + region STRING, + amount DECIMAL(10, 2) +); + +CREATE TABLE tickets_table ( + ticket_id INT, + region STRING +); + +CREATE OR REPLACE VIEW sales AS +SELECT + *, + SUM(amount) TO MEASURE total_sales +FROM sales_table; + +CREATE OR REPLACE VIEW tickets AS +SELECT + *, + COUNT(*) TO MEASURE ticket_count +FROM tickets_table; From ca5df60db2f51256d6c5a0843403a3089225e422 Mon Sep 17 00:00:00 2001 From: Chris Eubank <108756251+christianeu-db@users.noreply.github.com> Date: Fri, 28 Aug 2026 16:51:03 +0000 Subject: [PATCH 2/2] Add ASF license header to bi-sql-examples files Add the Apache Software Foundation license header to all files introduced in this PR: the HTML-comment style for Markdown files and the SQL line-comment style for .sql files. Co-authored-by: Isaac --- bi-sql-examples/README.md | 19 +++++++++++++++++++ bi-sql-examples/tableau/01-top-n-filters.sql | 17 +++++++++++++++++ .../tableau/02-lod-two-stage-aggregation.sql | 17 +++++++++++++++++ bi-sql-examples/tableau/03-sets.sql | 17 +++++++++++++++++ .../04-multi-table-joins-relationships.sql | 17 +++++++++++++++++ bi-sql-examples/tableau/README.md | 19 +++++++++++++++++++ bi-sql-examples/tableau/setup.sql | 17 +++++++++++++++++ 7 files changed, 123 insertions(+) diff --git a/bi-sql-examples/README.md b/bi-sql-examples/README.md index 28cb837f..50eb5dcd 100644 --- a/bi-sql-examples/README.md +++ b/bi-sql-examples/README.md @@ -1,3 +1,22 @@ + + BI SQL examples =============== diff --git a/bi-sql-examples/tableau/01-top-n-filters.sql b/bi-sql-examples/tableau/01-top-n-filters.sql index 51790901..c6a29a69 100644 --- a/bi-sql-examples/tableau/01-top-n-filters.sql +++ b/bi-sql-examples/tableau/01-top-n-filters.sql @@ -1,3 +1,20 @@ +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. + -- ============================================================================ -- Tableau BI SQL examples: Top N filters -- diff --git a/bi-sql-examples/tableau/02-lod-two-stage-aggregation.sql b/bi-sql-examples/tableau/02-lod-two-stage-aggregation.sql index fe4dadf5..5fad25a5 100644 --- a/bi-sql-examples/tableau/02-lod-two-stage-aggregation.sql +++ b/bi-sql-examples/tableau/02-lod-two-stage-aggregation.sql @@ -1,3 +1,20 @@ +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. + -- ============================================================================ -- Tableau BI SQL examples: LoDs for two-stage aggregation -- diff --git a/bi-sql-examples/tableau/03-sets.sql b/bi-sql-examples/tableau/03-sets.sql index 00883883..2b63fd1a 100644 --- a/bi-sql-examples/tableau/03-sets.sql +++ b/bi-sql-examples/tableau/03-sets.sql @@ -1,3 +1,20 @@ +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. + -- ============================================================================ -- Tableau BI SQL examples: sets (LoD calculation vs. built-in Set feature) -- diff --git a/bi-sql-examples/tableau/04-multi-table-joins-relationships.sql b/bi-sql-examples/tableau/04-multi-table-joins-relationships.sql index f7008c17..8b40f85e 100644 --- a/bi-sql-examples/tableau/04-multi-table-joins-relationships.sql +++ b/bi-sql-examples/tableau/04-multi-table-joins-relationships.sql @@ -1,3 +1,20 @@ +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. + -- ============================================================================ -- Tableau BI SQL examples: multi-table analysis (joins + relationships) -- diff --git a/bi-sql-examples/tableau/README.md b/bi-sql-examples/tableau/README.md index d7bbe9f6..b2e668b9 100644 --- a/bi-sql-examples/tableau/README.md +++ b/bi-sql-examples/tableau/README.md @@ -1,3 +1,22 @@ + + Tableau BI SQL examples ======================= diff --git a/bi-sql-examples/tableau/setup.sql b/bi-sql-examples/tableau/setup.sql index 47bda4ab..215d6d40 100644 --- a/bi-sql-examples/tableau/setup.sql +++ b/bi-sql-examples/tableau/setup.sql @@ -1,3 +1,20 @@ +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. + -- ============================================================================ -- Tableau BI SQL examples: setup --