[英]Multiple CTE in single query
是否可以将单个查询中的多个 CTE 与arel
组合在一起? 我正在寻找获得这样的结果的方法:
WITH cte1 AS (
...
),
WITH RECURSIVE cte2 AS (
...
),
WITH cte3 AS (
...
)
SELECT ... FROM cte3 WHERE ...
如您所见,我有一个递归 CTE 和两个非递归。
在顶部使用关键字WITH
一次 。 如果您的任何公用表表达式(CTE)是递归的(rCTE),您还必须在顶部添加一次关键字RECURSIVE
,即使并非所有CTE都是递归的:
WITH RECURSIVE
cte1 AS (...) -- can still be non-recursive
, cte2 AS (SELECT ...
UNION ALL
SELECT ...) -- recursive term
, cte3 AS (...)
SELECT ... FROM cte3 WHERE ...
如果指定了
RECURSIVE
,则它允许SELECT
子查询按名称引用自身。
大胆强调我的。 而且,更具洞察力:
RECURSIVE
另一个作用是不需要对WITH
查询进行排序 :查询可以引用列表后面的另一个查询。 (但是,未实现循环引用或相互递归。)如果没有RECURSIVE
,WITH
查询只能引用兄弟WITH
WITH
列表中较早的查询。
再次强调我的重点。 这意味着当使用RECURSIVE
关键字时, WITH
子句的顺序毫无意义 。
顺便说一句,因为cte1
和cte2
没有在外部SELECT
引用并且是纯SELECT
命令本身(没有附带效果),所以它们永远不会被执行(除非在cte3
引用)。
是。 你不重复WITH
。 你只需使用逗号:
WITH cte1 AS (
...
),
cte2 AS (
...
),
cte3 AS (
...
)
SELECT ... FROM 'cte3' WHERE ...
而且:只对字符串和日期常量使用单引号。 不要将它们用于列别名。 无论如何,它们不被允许用于CTE名称。
是的,可以在 SQL 中使用单个 WITH 子句创建多个公用表表达式。 两个不同的 CTE 是使用单个 WITH 子句创建的,并且用逗号分隔以创建多个 CTE。
使用单个采样多个 CTE
With EmpCount1(DeptName,TotalEmployees)
as
(
Select DeptName, COUNT(*) as TotalEmployees
from Tbl_EmpDetails
join Tbl_Dept Dept
on Tbl_EmpDetails.DeptId = Dept.DeptId
WHERE DeptName IN ('BI','DOTNET')
group by DeptName
),
EmpCount2(DeptName,TotalEmployees)
as
(
Select DeptName, COUNT(*) as TotalEmployees
from Tbl_EmpDetails
join Tbl_Dept Dept
on Tbl_EmpDetails.DeptId = Dept.DeptId
WHERE DeptName IN ('JAVA','AI')
group by DeptName
)
Select * from EmpCount1
UNION
Select * from EmpCount2
这是使用单个 With 子句创建多个公用表表达式的示例语法。
正如接受的答案正确所说的那样,每个 CTE 链只使用with
子句一次。 但是,为了完整起见,我想补充一点,它不会阻止您嵌套 CTE 。
如果cte2
用途cte1
, cte3
用途cte2
等,则热膨胀系数之间的依赖关系链是线性的,它被表达为with
用3层的CTE。 相反,如果cte2
不需要cte1
并且两者都只在cte3
中需要,则应考虑将它们嵌套在cte3
定义下( with cte3 as (with cte1 as (...), cte2 as (...) select...)
)。
然后 CTE 的语法反映了 CTE 之间的依赖树,并从字面上可视化了部分数据集的范围,这可以提高可读性并防止范围泄漏错误。 并非所有数据库供应商都支持它,但 Postgres 支持。
with cte1(id,capital) as (
values(1,'Prague'),(2,'Bratislava')
), cte2(id,code) as (
with cte2inner1(id,code) as (
values(1,'CZ'),(2,'SK')
), cte2inner2(id,country) as (
values(1,'Czech Republic'),(2,'Slovakia')
)
select id,country from cte2inner1 join cte2inner2 using (id)
)
select *
from cte1 join cte2 using (id)
--join cte2inner1 not possible here
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.