J.D
J.D

Reputation: 444

Can I select several tables in the same WITH query?

I have a long query with a with structure. At the end of it, I'd like to output two tables. Is this possible?

(The tables and queries are in snowflake SQL by the way.)

The code looks like this:

with table_a as (
               select id, 
                      product_a
               from x.x ),
     table_b as (
               select id, 
                      product_b
               from x.y ),
     table_c as ( 

..... many more alias tables and subqueries here .....

             )

select * from table_g where z = 3 ;

But for the very last row, I'd like to query table_g twice, once with z = 3 and once with another condition, so I get two tables as the result. Is there a way of doing that (ending with two queries rather than just one) or do I have to re-run the whole code for each table I want as output?

Upvotes: 2

Views: 500

Answers (2)

JNevill
JNevill

Reputation: 50019

One query = One result set. That's just the way that RDBMS's work.

A CTE (WITH statement) is just syntactic sugar for a subquery.

For instance, a query similar to yours:

with table_a as (
               select id, 
                      product_a
               from x.x ),
     table_b as (
               select id, 
                      product_b
               from x.y ),
     table_c as (     
               select id, 
                      product_c
               from x.z ),

select * 
from table_a
   inner join table_b on table_a.id = table_b.id
   inner join table_c on table_b.id = table_c.id;

Is 100% identical to:

select *
from
  (select id, product_a from x.x) table_a
  inner join (select id, product_b from x.y) table_b
      on table_a.id = table_b.id
  inner join (select id, product_c from x.z) table_c
      on table_b.id = table_c.id

The CTE version doesn't give you any extra features that aren't available in the non-cte version (with the exception of a recursive cte) and the execution path will be 100% the same (EDIT: Please see Simon's answer and comment below where he notes that Snowflake may materialize the derived table defined by the CTE so that it only has to perform that step once should the CTE be referenced multiple times in the main query). As such there is still no way to get a second result set from the single query.

Upvotes: 3

Simeon Pilgrim
Simeon Pilgrim

Reputation: 25903

While they are the same syntactically, they don't have the same performance plan.

The first case can be when one of the stages in the CTE is expensive, and is reused via other CTE's or join to many times, under Snowflake, use them as a CTE I have witness it running the "expensive" part only a single time, which can be good so for example like this.

WITH expensive_select AS (
    SELECT a.a, b.b, c.c
    FROM table_a AS a
    JOIN table_b AS b
    JOIN table_c AS c
    WHERE complex_filters
), do_some_thing_with_results AS (
    SELECT stuff
    FROM expensive_select
    WHERE filters_1
), do_some_agregation AS (
    SELECT a, SUM(b) as sum_b
    FROM expensive_select
    WHERE filters_2
)
SELECT a.a
    ,a.b
    ,b.stuff
    ,c.sum_b
FROM expensive_select AS a
LEFT JOIN do_some_thing_with_results AS b ON a.a = b.a
LEFT JOIN do_some_agregation AS c ON a.a = b.a;

This was originally unrolled, and the expensive part was some VIEWS that the date range filter that was applied at the top level were not getting pushed down (due to window functions) so resulted in full table scans, multiple times. Where pushing them into the CTE the cost was paid once. (In our case putting date range filters in the CTE made Snowflake notice the filters and push them down into the view, and things can change, a few weeks later the original code ran as good as the modified, so they "fixed" something)

In other cases, like this the different paths that used the CTE use smaller sub-sets of the results, so using the CTE reduced the remote IO so improved performance, there then was more stalls in the execution plan.

I also use CTEs like this to make the code easier to read, but giving the CTE a meaningful name, but the aliasing it to something short, for use. Really love that.

Upvotes: 2

Related Questions