Common Table Expressions - 公共表表达式
WITH regional_sales AS (
SELECT region, SUM(amount) AS total_sales FROM orders GROUP BY region
), top_regions AS (
SELECT region FROM regional_sales
WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
)
SELECT region,
product,
SUM(quantity) AS product_units,
SUM(amount) AS product_sales
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;
It was introduced in SQL:1999, the fourth SQL revision.
UNION 其实全名叫 UNION DISTINCT
> select 1 as n union select 1;
+---+
| n |
+---+
| 1 |
+---+
1 rows in set
> select 1 as n union all select 1
+---+
| n |
+---+
| 1 |
| 1 |
+---+
2 rows in set
with_clause:
WITH [RECURSIVE]
cte_name [(col_name [, col_name] ...)] AS (subquery)
[, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...
with teacher as (
select username from passport where role = 1
), student as (
select username from passport where role = 2
)
WITH RECURSIVE cte (n) AS
(
SELECT 1
UNION ALL
SELECT n + 1 FROM cte WHERE n < 5
)
SELECT * FROM cte;
CTE 对语句的优化,和具体数据库实现有关
已实现简单的 linear sequence 举例
WITH RECURSIVE XXX AS (
{非递归项}
UNION ALL
{递归项}
) select ...
执行步骤如下:
执行非递归项 其结果作为递归项中对结果的引用, 同时将这部分结果放入临时的working table中
重复执行如下步骤,直到working table为空:
a. 计算递归项,用当前 working table 的内容替换递归自引用。 将剩下的所有行包括在递归查询的结果中,并且也把它们放在一个临时的中间表中。
b. 用中间表的内容替换 working table 的内容,然后清空中间表。
求格力电器 (000651) 最长上涨天数
with recursive t1 as (
select *,row_number() over(order by tdate) rn
from stktrade where sid='000651'
),
t2 as (
select *,0 rise from t1 where rn=1
union all
select t1.*, if(t1.close>t2.close,t2.rise+1,0)
from t1 join t2 on t1.rn=t2.rn+1
)
select max(rise) from t2;
WITH RECURSIVE search_graph(id, link, data, depth, path, cycle) AS (
SELECT g.id, g.link, g.data, 1, ARRAY[g.id], false
FROM graph g
UNION ALL
SELECT g.id, g.link, g.data, sg.depth + 1, path || g.id, g.id = ANY(path)
FROM graph g, search_graph sg
WHERE g.id = sg.link AND NOT cycle
) SELECT * FROM search_graph;
从理论上讲: CTE和子查询的性能应该相同,因为它们都向查询优化器提供了相同的信息。
CTE:
临时表:
另外,如果您有一个不止一次使用的复杂CTE(子查询),那么将其存储在临时表中通常会提高性能。该查询仅执行一次。