【问题标题】: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 进行标记。

标签: sql view


【解决方案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 视为命名派生表而不是临时表......即使它们不仅仅是派生表

      【讨论】:

        猜你喜欢
        • 2014-02-15
        • 2019-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        相关资源
        最近更新 更多