TPC-DS Q5 — Three-Channel Sales-Returns Union with ROLLUP
TPC-DS benchmark · all TPC-DS queries
Unions sales and returns per channel then aggregates with ROLLUP
Representative SQL
Rendered for DataFusion with default parameters.
WITH ssr AS ( SELECT s_store_id, SUM(sales_price) AS sales, SUM(profit) AS profit, SUM(return_amt) AS returns, SUM(net_loss) AS profit_loss FROM ( SELECT ss_store_sk AS store_sk, ss_sold_date_sk AS date_sk, ss_ext_sales_price AS sales_price, ss_net_profit AS profit, CAST(0 AS DECIMAL(7, 2)) AS return_amt, CAST(0 AS DECIMAL(7, 2)) AS net_loss FROM store_sales UNION ALL SELECT sr_store_sk AS store_sk, sr_returned_date_sk AS date_sk, CAST(0 AS DECIMAL(7, 2)) AS sales_price, CAST(0 AS DECIMAL(7, 2)) AS profit, sr_return_amt AS return_amt, sr_net_loss AS net_loss FROM store_returns ) AS salesreturns, date_dim, store WHERE date_sk = d_date_sk AND d_date BETWEEN CAST('1998-08-04' AS DATE) AND ( CAST('1998-08-04' AS DATE) + INTERVAL '14 DAY' ) AND store_sk = s_store_sk GROUP BY s_store_id), csr AS ( SELECT cp_catalog_page_id, SUM(sales_price) AS sales, SUM(profit) AS profit, SUM(return_amt) AS returns, SUM(net_loss) AS profit_loss FROM ( SELECT cs_catalog_page_sk AS page_sk, cs_sold_date_sk AS date_sk, cs_ext_sales_price AS sales_price, cs_net_profit AS profit, CAST(0 AS DECIMAL(7, 2)) AS return_amt, CAST(0 AS DECIMAL(7, 2)) AS net_loss FROM catalog_sales UNION ALL SELECT cr_catalog_page_sk AS page_sk, cr_returned_date_sk AS date_sk, CAST(0 AS DECIMAL(7, 2)) AS sales_price, CAST(0 AS DECIMAL(7, 2)) AS profit, cr_return_amount AS return_amt, cr_net_loss AS net_loss FROM catalog_returns ) AS salesreturns, date_dim, catalog_page WHERE date_sk = d_date_sk AND d_date BETWEEN CAST('1998-08-04' AS DATE) AND ( CAST('1998-08-04' AS DATE) + INTERVAL '14 DAY' ) AND page_sk = cp_catalog_page_sk GROUP BY cp_catalog_page_id), wsr AS ( SELECT web_site_id, SUM(sales_price) AS sales, SUM(profit) AS profit, SUM(return_amt) AS returns, SUM(net_loss) AS profit_loss FROM ( SELECT ws_web_site_sk AS wsr_web_site_sk, ws_sold_date_sk AS date_sk, ws_ext_sales_price AS sales_price, ws_net_profit AS profit, CAST(0 AS DECIMAL(7, 2)) AS return_amt, CAST(0 AS DECIMAL(7, 2)) AS net_loss FROM web_sales UNION ALL SELECT ws_web_site_sk AS wsr_web_site_sk, wr_returned_date_sk AS date_sk, CAST(0 AS DECIMAL(7, 2)) AS sales_price, CAST(0 AS DECIMAL(7, 2)) AS profit, wr_return_amt AS return_amt, wr_net_loss AS net_loss FROM web_returns LEFT OUTER JOIN web_sales ON ( wr_item_sk = ws_item_sk AND wr_order_number = ws_order_number ) ) AS salesreturns, date_dim, web_site WHERE date_sk = d_date_sk AND d_date BETWEEN CAST('1998-08-04' AS DATE) AND ( CAST('1998-08-04' AS DATE) + INTERVAL '14 DAY' ) AND wsr_web_site_sk = web_site_sk GROUP BY web_site_id)SELECT channel, id, SUM(sales) AS sales, SUM(returns) AS returns, SUM(profit) AS profitFROM ( SELECT 'store channel' AS channel, 'store' || s_store_id AS id, sales, returns, ( profit - profit_loss ) AS profit FROM ssr UNION ALL SELECT 'catalog channel' AS channel, 'catalog_page' || cp_catalog_page_id AS id, sales, returns, ( profit - profit_loss ) AS profit FROM csr UNION ALL SELECT 'web channel' AS channel, 'web_site' || web_site_id AS id, sales, returns, ( profit - profit_loss ) AS profit FROM wsr) AS xGROUP BY ROLLUP ( channel, id )ORDER BY channel, idLIMIT 100Representative DataFrame
Expression family (Polars, PySpark, DataFusion), default parameters.
def q5_expression_impl(ctx: DataFrameContext) -> Any: col = ctx.col lit = ctx.lit date_filtered = _date_window_expression(ctx, 5, "1998-08-04", days=14)
def channel( channel_name: str, id_prefix: str, dimension_table: str, dimension_key: str, dimension_id: str, sales_spec: tuple[str, str, str, str, str], returns_spec: tuple[str, str, str, str, str], returns_join: tuple[str, tuple[str, str], tuple[str, str]] | None = None, ) -> Any: sales_table, sales_dim_col, sales_date_col, sales_price_col, sales_profit_col = sales_spec returns_table, returns_dim_col, returns_date_col, returns_amt_col, returns_loss_col = returns_spec sales_part = ctx.get_table(sales_table).select( [ col(sales_dim_col).alias("dim_sk"), col(sales_date_col).alias("date_sk"), col(sales_price_col).alias("sales_price"), col(sales_profit_col).alias("profit"), lit(0.0).alias("return_amt"), lit(0.0).alias("net_loss"), ] ) returns = ctx.get_table(returns_table) if returns_join is not None: join_table, left_on, right_on = returns_join returns = returns.join( ctx.get_table(join_table), left_on=list(left_on), right_on=list(right_on), how="left" ) returns_part = returns.select( [ col(returns_dim_col).alias("dim_sk"), col(returns_date_col).alias("date_sk"), lit(0.0).alias("sales_price"), lit(0.0).alias("profit"), col(returns_amt_col).alias("return_amt"), col(returns_loss_col).alias("net_loss"), ] ) return ( ctx.concat([sales_part, returns_part]) .join(date_filtered, left_on="date_sk", right_on="d_date_sk") .join(ctx.get_table(dimension_table), left_on="dim_sk", right_on=dimension_key) .group_by(dimension_id) .agg( [ col("sales_price").sum().alias("sales"), col("profit").sum().alias("profit_sum"), col("return_amt").sum().alias("returns"), col("net_loss").sum().alias("profit_loss"), col("sales_price").count().alias("sales_n"), col("profit").count().alias("profit_sum_n"), col("return_amt").count().alias("returns_n"), col("net_loss").count().alias("profit_loss_n"), ] ) .with_columns( [ ctx.when(col(f"{name}_n") > lit(0)).then(col(name)).otherwise(lit(None)).alias(name) for name in ("sales", "profit_sum", "returns", "profit_loss") ] ) .with_columns( [ lit(channel_name).alias("channel"), (lit(id_prefix) + col(dimension_id)).alias("id"), (col("profit_sum") - col("profit_loss")).alias("profit"), ] ) .select(["channel", "id", "sales", "returns", "profit"]) )
# fmt: off specs = ( ("store channel", "store", "store", "s_store_sk", "s_store_id", ("store_sales", "ss_store_sk", "ss_sold_date_sk", "ss_ext_sales_price", "ss_net_profit"), ("store_returns", "sr_store_sk", "sr_returned_date_sk", "sr_return_amt", "sr_net_loss")), ("catalog channel", "catalog_page", "catalog_page", "cp_catalog_page_sk", "cp_catalog_page_id", ("catalog_sales", "cs_catalog_page_sk", "cs_sold_date_sk", "cs_ext_sales_price", "cs_net_profit"), ("catalog_returns", "cr_catalog_page_sk", "cr_returned_date_sk", "cr_return_amount", "cr_net_loss")), ("web channel", "web_site", "web_site", "web_site_sk", "web_site_id", ("web_sales", "ws_web_site_sk", "ws_sold_date_sk", "ws_ext_sales_price", "ws_net_profit"), ("web_returns", "ws_web_site_sk", "wr_returned_date_sk", "wr_return_amt", "wr_net_loss"), ("web_sales", ("wr_item_sk", "wr_order_number"), ("ws_item_sk", "ws_order_number"))), ) # fmt: on combined = ctx.concat([channel(*spec) for spec in specs]) return _sales_returns_rollup_expression(ctx, combined)Get the exact query for your run
The blocks above are representative. To get the precise statement a specific platform runs at a specific scale, substitute your own values:
from benchbox import TPCDS
bench = TPCDS(scale_factor=1.0) # your scale factorqueries = bench.get_queries(dialect="datafusion") # your platform's dialect; drop dialect= for native SQLprint(queries['5'])Parameter substitution for this benchmark is seed-driven; pass a seed for a specific stream’s parameters:
print(bench.get_query(5, scale_factor=1.0, seed=42, dialect="datafusion"))For the DataFrame form:
from benchbox.core.query_catalog import get_dataframe_render
print(get_dataframe_render('tpcds', '5', family="expression").source) # or family="pandas"Source
Query text: _sources/tpc-ds/query_templates/query5.tpl