CTE is a temporary result take from a SQL statement
A second approach to create temporary tables for query data instead of using sub queries in a FROM clause
CTE's are a good alternative to sub queries.
CTE can be referenced multiple times in multiple places in query statement
Lifetime of CTE is equal to the lifetime of a query.
Types of CTE
Materialized
Not materialized
Syntax
with cte_table ( column_list ) as ( cte_query_definition)with num as (select*fromgenerate_series(1, 5) as id)select*from num; id ----12345
CTE with Join
with cte_director as (select movie_id, movie_name, d.director_id, first_namefrom moviesinner join directors d on d.director_id = movies.director_id)select*from cte_directorlimit5; movie_id | movie_name | director_id | first_name ----------+------------------------+-------------+------------20 | Let the Right One In | 1 | Tomas46 | There Will Be Blood | 2 | Paul40 | The Darjeeling Limited | 3 | Wes30 | Rushmore | 3 | Wes15 | Grand Budapest Hotel | 3 | Wes
CTE with CASE
WITH cte_film AS (SELECT movie_name, movie_length title, (CASEWHEN movie_length <100THEN'Short'WHEN movie_length <120THEN'Medium'ELSE'Long'END) lengthFROM movies)SELECT*FROM cte_filmWHERElength='Long'ORDER BY titlelimit5; movie_name | title | length--------------------+-------+-------- The Wizard of Oz | 120 | Long Spirited Away | 120 | LongTop Gun | 121 | Long Leon | 123 | Long Gone with the Wind | 123 | Long
Complex query example
WITH cte_movie_count AS (SELECT d.director_id,SUM(COALESCE(r.revenues_domestic, 0) +COALESCE(r.revenues_international, 0)) AS total_revenuesFROM directors dINNER JOIN movies mv ON mv.director_id = d.director_idINNER JOIN movies_revenues r ON r.movie_id = mv.movie_idGROUP BY d.director_id )SELECT d.director_id, d.first_name, d.last_name, cte.total_revenuesFROM cte_movie_count cteINNER JOIN directors d ON d.director_id = cte.director_idLIMIT5;
CTE to perform DML
Loading Sample Data
createtablearticles( id serial, article text);createtabledeleted_articles( id serial, article text);insert into articles (article)values ('article 1'), ('article 2'), ('article 3'), ('article 4'), ('article 5');
Query
select*from articles; id | article ----+-----------1 | article 12 | article 23 | article 34 | article 45 | article 5select*from deleted_articles; id | article ----+---------(0rows)-- deleting from one table-- returning fromwith cte_delete_article as (deletefrom articleswhere id =1 returning *)insertinto deleted_articlesselect*from cte_delete_article;select*from deleted_articles;-- output id | article ----+-----------1 | article 1(1row)