是否可以在单个查询中将多个 CTE 与arel?我正在寻找获得这样结果的方法:
WITH cte1 AS (
...
),
WITH RECURSIVE cte2 AS (
...
),
WITH cte3 AS (
...
)
SELECT ... FROM cte3 WHERE ...
如您所见,我有一个递归 CTE 和两个非递归 CTE。
是否可以在单个查询中将多个 CTE 与arel?我正在寻找获得这样结果的方法:
WITH cte1 AS (
...
),
WITH RECURSIVE cte2 AS (
...
),
WITH cte3 AS (
...
)
SELECT ... FROM cte3 WHERE ...
如您所见,我有一个递归 CTE 和两个非递归 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
再次大胆强调我的。这意味着当使用了关键词时,WITH从句的顺序是没有意义的。RECURSIVE
顺便说一句,由于cte1和cte2在示例中没有在外部引用SELECT并且本身是普通SELECT命令(没有附带影响),它们永远不会被执行(除非在 中引用cte3)。
是的。你不要重复WITH. 您只需使用逗号:
WITH cte1 AS (
...
),
cte2 AS (
...
),
cte3 AS (
...
)
SELECT ... FROM 'cte3' WHERE ...
并且:仅对字符串和日期常量使用单引号。不要将它们用于列别名。无论如何,它们都不允许用于 CTE 名称。
正如公认的答案正确地说,该with子句在每个 CTE 链中仅使用一次。但是,为了完整起见,我想补充一点,它不会阻止您嵌套 CTE。
如果cte2uses cte1、cte3usescte2等,则CTE之间的依赖链是线性的,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
问题原因:在这里,您不必使用多个 WITH 子句来组合多个 CTE。
解决方案:可以在 SQL 中使用单个 WITH 子句创建多个公用表表达式。使用 Single WITH 子句创建两个不同的 CTE,并用逗号分隔以创建多个 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 子句创建多个公用表表达式的示例语法。