在 SQL 中是不是可以在 WITH 中使用 WITH
Posted
技术标签:
【中文标题】在 SQL 中是不是可以在 WITH 中使用 WITH【英文标题】:Is it possible in SQL to use WITH inside a WITH在 SQL 中是否可以在 WITH 中使用 WITH 【发布时间】:2014-06-12 01:46:59 【问题描述】:在 SQL 中,可以将 WITH 放在 WITH 中吗?
以下面的查询为例,
WITH Temp ([Description], [Amount], [OverdueBy])
AS
(select Description, SUM(Amount) as Amount, (DATEDIFF(day,DueDate,GETDATE())) as OverdueBy from brvAPAllInvoices
Where PaidDate is null and APCo = 1 and Amount > 0
Group By Description, DueDate, APRef
)
select * from Temp
我想根据上述查询创建一个“虚拟”临时表。是否可以使用另一个 WITH 来包含它?
类似这样的事情:
WITH Temp2 ([Description], [Amount], [OverdueBy])
AS
(
WITH Temp ([Description], [Amount], [OverdueBy])
AS
(select Description, SUM(Amount) as Amount, (DATEDIFF(day,DueDate,GETDATE())) as OverdueBy from brvAPAllInvoices
Where PaidDate is null and APCo = 1 and Amount > 0
Group By Description, DueDate, APRef
)
select * from Temp)
select * from Temp2
【问题讨论】:
你尝试的时候发生了什么? Msg 156, Level 15, State 1, Line 4 关键字“WITH”附近的语法不正确。消息 319,级别 15,状态 1,第 4 行关键字“with”附近的语法不正确。如果此语句是公用表表达式、xmlnamespaces 子句或更改跟踪上下文子句,则前面的语句必须以分号结束。消息 102,级别 15,状态 1,第 12 行 ')' 附近的语法不正确。 确保使用 实际 RDBMS 进行标记。 【参考方案1】:根据您的 dbms,您可以有多个 WITH 语句,无论是否嵌套。 (用 PostgreSQL 说明。)SQL Server doesn't allow nesting common table expressions。 (搜索CTE_query_definition。)
嵌套
with today as (
with yesterday as (select current_date - interval '1' day as yesterday)
select yesterday + interval '1' day as today from yesterday
)
select cast(today as date) from today
今天
--
2014-06-11
当您嵌套公用表表达式时,嵌套的 CTE 在其封闭的 CTE 之外不可见。
with today as (
with yesterday as (select current_date - interval '1' day as yesterday)
select yesterday + interval '1' day as today from yesterday
)
select * from yesterday
错误:关系“昨天”不存在
未嵌套
with yesterday as (
select current_date - interval '1' day as yesterday
),
today as (
select yesterday + interval '1' day as today from yesterday
)
select cast(yesterday as date) as dates from yesterday
union all
select cast(today as date) from today
日期
--
2014-06-10
2014-06-11
当您使用连续的、未嵌套的 CTE 时,较早的 CTE 对后面的 CTE 可见,但反之则不然。
with today as (
select yesterday + interval '1' day as today from yesterday
),
yesterday as (
select current_date - interval '1' day as yesterday
)
select yesterday from yesterday
union all
select today from today
错误:关系“昨天”不存在
【讨论】:
【参考方案2】:不,您不能在 CTE 中定义 CTE,但是您可以在单个语句中定义多个 CTE 并引用其他 CTE。
; with a as (
select * from some_table
),
b as (
select *
from another_table t
inner join a ON (t.key = a.key)
)
select *
from b
【讨论】:
【参考方案3】:您通常会执行以下操作;
WITH Temp ([Description], [Amount], [OverdueBy])
AS
(select Description, SUM(Amount) as Amount, (DATEDIFF(day,DueDate,GETDATE())) as OverdueBy from brvAPAllInvoices
Where PaidDate is null and APCo = 1 and Amount > 0
Group By Description, DueDate, APRef
), Temp2 ([Description], [Amount], [OverdueBy]) AS
(
SELECT * FROM Temp
)
select * from Temp2
尽管在您设计的示例中,显然没有太多用处,因为两个表结构几乎相同。我也倾向于将 CTE 视为命名派生表而不是临时表......即使它们不仅仅是派生表
【讨论】:
以上是关于在 SQL 中是不是可以在 WITH 中使用 WITH的主要内容,如果未能解决你的问题,请参考以下文章