什么是CTE?
WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到。是为了让SQL语句的可读性更高些。
特别对于UNION ALL比较有用。因为UNION ALL的每个部分可能相同,但是如果每个部分都去执行一遍的话,则成本太高,所以可以使用WITH AS短语,则只要执行一遍即可。如果WITH AS短语所定义的表名被调用两次以上,则优化器会自动将WITH AS短语所获取的数据放入一个TEMP表里,如果只是被调用一次,则不会。而提示materialize则是强制将WITH AS短语里的数据放入一个全局临时表里。很多查询通过这种方法都可以提高速度。
WITH AS的注意事项
- CTE后面必须直接跟使用CTE的SQL语句(如select、insert、update等),否则,CTE将失效。如下面的SQL语句将无法正常使用CTE
with
cr as
(
select CountryRegionCode from person.CountryRegion where Name like 'C%'
)
select * from person.CountryRegion -- 应将这条SQL语句去掉
-- 使用CTE的SQL语句应紧跟在相关的CTE后面 --
select * from person.StateProvince where CountryRegionCode in (select * from cr)
-- Set up your CTE
WITH match_list AS (
SELECT
country_id,
id
FROM match
WHERE (home_goal + away_goal) >= 10)
-- CTE完成,下面是使用match_list的SQL语句
SELECT
l.name AS league,
COUNT(match_list.id) AS matches
FROM league AS l
-- Left Join CTE表
LEFT JOIN match_list ON l.id = match_list.country_id
GROUP BY l.name;
- CTE中可以使用的语句
2.1 JOIN
WITH match_list AS (
-- Select the league name, date, home, and away goals
SELECT
l.name AS league,
m.date,
m.home_goal,
m.away_goal,
(m.home_goal + m.away_goal) AS total_goals
FROM match AS m
LEFT JOIN league as l ON m.country_id = l.id)
- CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔,如下面的SQL语句所示
-- Create your home team CTE 第一个CTE
WITH home AS (
-- Select the match id and team long name
SELECT m.id, t.team_long_name
FROM match AS m
LEFT JOIN team AS t ON m.hometeam_id = t.team_api_id),
-- Create your away team CTE. 第二个CTE(不需要WITH了)
away AS (
-- Select the match id and team long name
SELECT m.id, t.team_long_name
FROM match AS m
LEFT JOIN team AS t ON m.awayteam_id = t.team_api_id)
-- LEFT JOIN CTE表相关的SQL
SELECT
m.stage,
m.date,
home.team_long_name AS home_team,
away.team_long_name AS away_team,
m.home_goal,
m.away_goal
FROM match AS m
-- Join the CTEs onto the match table
LEFT JOIN away ON m.id = away.id
LEFT JOIN home ON m.id = home.id
WHERE m.season = '2014/2015';
Reference:
https://www.jb51.net/article/30976.htm