This question already has answers here:
How to use multiple CTEs in a single SQL query?
(4 answers)
Closed 5 years ago.
I'm trying to do something like:
WITH megalodon_view AS (
-- 200 lines of gibberish
)
WITH RECURSIVE traverse_table AS (
-- big queries with multiple uses of megalodon_view for recursive traversing
)
Observe it's not a mather of defining 2 CTEs, but to use on within the scope of the other.
I'd like to use it in production, so I want preferrably not to create anything physically
You can specify this as:
WITH recursive megalodon_view AS (
-- 200 lines of gibberish
),
traverse_table AS (
-- big queries with multiple uses of megalodon_view for recursive traversing
)
select . . .;
The with recursive is needed only once, for the first CTE (even though that one is not recursive).
Without exact query it is hard to say what are you trying to achieve. Anyway you could nest WITH like:
WITH RECURSIVE t(n) AS (
SELECT *
FROM (WITH cte AS (SELECT 1 )
SELECT * FROM cte
) sub
UNION ALL
SELECT n+1 FROM t WHERE n < 100
)
SELECT COUNT(*) FROM t;
DBFiddle Demo
Related
Until today I thought that the CTE had to go before the main SELECT clause, but it appears that a CTE can be dropped into any subselect. As an example:
-- tested on BigQuery, Redshift, MySQL, Postgres
SELECT CONCAT(Odd.num, Even.num) FROM
(WITH Numbers AS (SELECT 1 AS num UNION ALL SELECT 3 UNION ALL SELECT 5) SELECT * FROM Numbers) Odd,
(WITH Numbers AS (SELECT 2 AS num UNION ALL SELECT 4 UNION ALL SELECT 6) SELECT * FROM Numbers) Even
Outside of just playing around with things though, is there ever a case for this sort of "embedded" CTE, or is there no reason to ever have it outside of the top, as if it's a variable declaration?
Not only that, you can have CTEs inside of CTEs.
WITH CTE1 AS (
WITH CTE2 AS (
…
)
)
SELECT …
I had to work on someone’s query that did this 13 levels deep. What a pain. The main reason this isn’t good is that it makes a mess of readability. I think what you are describing isn’t quite as bad as it keeps subsections of the query together. Doing oddball things like this generally leads to confusion when others try to understand your query.
This question already has an answer here:
BigQuery GENERATE_UUID() and CTE's
(1 answer)
Closed 1 year ago.
I'm trying to generate a UUID within a with clause on GBQ and then use it in a subsequent with clause for a join.
with q1 as (
select generate_uuid() as uuid
), q2 as (
select uuid from q1
)
select * from q1
union all
select * from q2
This returns two distinct uuid.
How would I go about generating an ID that stays the same across with clauses?
I'll start with the reason behind this discrepancy.
TLDR; as of today there is no option to force BigQuery to materialize CTE results. It'd be useful when a CTE referenced more than once in a statement.
see below query:
with cte_1 as (
select count(1) as row_count
from `bigquery-public-data.austin_311.311_service_requests` as sr
)
, cte_2 as (
select row_count
from cte_1
)
select row_count
from cte_1
union all
select row_count
from cte_2;
when the execution plan is examined, you'll see 2 Input stage for referenced sr table.
It'd be great if we have an option to materialize CTE results. As I remember, oracle has this implicitly if CTE used more than once or explicitly via hints.
materializing q1 explicitly to table then use it twice might be a workaround. I'd prefer temporary table.
the drawback is; the cost may increase if your project uses on-demand pricing. (rather than flat-rate)
Because subquery always executes each time it is called, so with your query, the generate_uuid will be called twice for both q1 and q2 tables.
I suggest you save the generated UUID to a table, then query from this to make sure the UUID is the same from both tables.
I have a (postgresql) query, that goes like
with
recursive account_tree as (<recursive function depending on path>), -- 1
path as (<some other query>) -- 2
select * from account_tree;
This works perfectly fine.
But when I reorder the with queries to that
with
path as (<some other query>), -- 2
recursive account_tree as (<recursive function depending on path>) -- 1
select * from account_tree;
it suddenly shows a syntax error. This behaviour doesn't occur, when I have standard non-recursive queries. With non-recursive queries, I can order them, as they please me.
Why does it do that?
The recursive keyword always goes right behind WITH regardless which of the CTE is actually the recursive one:
with recursive path as (
<some other query>
), account_tree as (
<recursive function depending on path>
)
select *
from account_tree;
recursive refers to the entire with clause. So just use:
with recursive path as (<some other query>), -- 2
What recursive really means is that Postgres will search for "table" names first as CTEs and then as tables/views in the recursive part of the CTE. The issue is really resolving identifiers. It has no effect on other CTEs.
This question already has answers here:
Oracle: Using Pseudo column value in the same Select statement
(3 answers)
Closed 9 years ago.
Folks I found similar but not exact questions on this forum - pardon me if i have not done enough searching for them. This is my question..in Oracle
select ( t.value*2) as inst2, (inst2 * 3) as inst3
from table t;
the thinking behind is if f() = t.value*2 is an expensive call, then we do not need to make that twice..or is there an alternative query structure i could use (I am trying to achieve this in CTAS)
thanks in advance.
Another option:
with cte as (
select t.value*2 as inst2
)
select
cte.inst2,
(cte.inst2*3) as inst3
from cte
This is actually the same as in bluefeet's reply, but I would consider it easier to understand with the with-syntax.
If you want to use an alias in the second calculation, then you will want to use a subquery:
select inst2,
(inst2 * 3) as inst3
from
(
select t.value*2 as inst2
from table t
)
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Multiple Select Statements using SQL Server 2005 “WITH” Statement
There's any way to get multiple result-sets from a query using WITH clause?
I'm using MS SQL 2005.
;with temp as
(
SELECT '1' as [Sample]
)
--SELECT COUNT(*) FROM temp
SELECT * FROM temp
This works with each select (count or *), but I need to return both result-sets from the same "temp".
Is that possible?
Use UNION ALL:
;with temp as
(
SELECT '1' as [Sample]
)
SELECT COUNT(*) FROM temp
UNION ALL
SELECT * FROM temp
I'd suggest you need to re-work whatever was meant to consume this pair of result sets so that it doesn't need to know how many results are going to be returned before the results arrive. If that's not the case, I can't think of where else you'd need to retrieve the COUNT of the result set as well as the result set itself.