cte tsql 使用变量

Posted

技术标签:

【中文标题】cte tsql 使用变量【英文标题】:cte tsql using variable 【发布时间】:2015-06-05 13:59:06 【问题描述】:

我有一个表函数,其中包含一些 CTE 表,最终汇总为返回的 select 语句。在其中一个 CTE 表中,我使用了 @variable。它与我为函数声明的@variable 相同。当我尝试保存函数时,我收到此错误:

Lookup Error - SQL Server Database Error: Parameters were not supplied for the function 'forecast_baseline'.

在 CTE 表中使用 @variable 有问题吗?我可以提供代码,但似乎没有将函数 @variable 传递给 CTE 表,因此编译器不喜欢它。

ALTER function [eo].[forecast_baseline] (@monthkey as char(6)) 
  returns @results table(
  [billing_date] date,
  [year] int,
  [type] varchar(max),
  [dollars] float,
  [units] float,
  [CC] int,
  [offering] varchar(max),
  [IntegratedReleasePlanNm] varchar(max),
  [ProjectId] varchar(max),
  [ProjectNm]  varchar(max),
  [ModelEstimateId] varchar(max),
  [query] varchar(max),
  [ItemGroupId]  varchar(max),
  CashflowType varchar(12),
  plotdate datetime
  )
  as
  begin
    declare @StartTime datetime = (SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(getdate())-1),getdate()),101))
    declare @EndTime datetime = DATEADD(year, +5, @StartTime)
    declare @Interval int = 1;

    WITH yearsinmonths (
      [datetimemonth], 
      [enddatetimemonth]) AS ( 
          SELECT
            @StartTime datetimemonth, 
            DATEADD(month, @Interval, @StartTime) AS enddatetimemonth
          UNION ALL
          SELECT
            EndRange, 
            DATEADD(month, @Interval, enddatetimemonth)
          FROM 
            cSequence 
          WHERE 
            DATEADD(month, @Interval, enddatetimemonth) < @EndTime
    ), 

    forecast_baseline (
      [billing_date],
      [year],
      [type],
      [dollars],
      [units],
      [CC],
      [offering],
      [IntegratedReleasePlanNm],
      [ProjectId],
      [ProjectNm],
      [ModelEstimateId],
      [query],
      [ItemGroupId],
      [CashflowType]) as (
          select 
            dateadd(month,-1,convert(date, a.CHARGE_MONTH+'01', 112))
            ,year(dateadd(month,-1,convert(date, a.CHARGE_MONTH+'01', 112)))
            ,'Baseline'
            ,sum(cast(a.CHARGE_AMOUNT as money))
            ,sum(cast (PPGUNITS as float))
            ,ORG_CC
            ,[offering]
            ,'Baseline'
            ,'baseline'
            ,'baseline'
            ,'baseline'
            ,'baseline'
            ,'N/A'
            ,'N/A'
          from 
            [sources].[feeds].[MARS2IEO_MARS_BD12_INV_LOB_EXTRACTS] a join sources.[md].[MARS_ITEMID_MAPPING] b 
              on a.offering=b.itemid 
          where 
            host_name is not null 
            and (a.org_sort_code like ('KBBFA%') or 
                a.org_sort_code like ('KBBFB%') or
                a.org_sort_code like ('KBBDD%'))
            and b.category in ('server','disk','tape')
            and cast(year(dateadd(month,-1,convert(date,     a.CHARGE_MONTH+'01', 112))) as char(4)) + RIGHT('00' + CONVERT(VARCHAR,month(dateadd(month,-1,convert(date, a.CHARGE_MONTH+'01', 112)))), 2) <= @monthkey -- this is the line that throws the error
          group by 
            offering
            ,ORG_CC
            ,dateadd(month,-1,convert(date, a.CHARGE_MONTH+'01', 112))
            ,year(dateadd(month,-1,convert(date, a.CHARGE_MONTH+'01', 112)))
)

    INSERT INTO @results (
      [billing_date],
      [year],
      [type],
      [dollars],
      [units],
      [CC],
      [offering],
      [IntegratedReleasePlanNm],
      [ProjectId],
      [ProjectNm],
      [ModelEstimateId],
      [query],
      [ItemGroupId],
      [CashflowType]
      )
      select 
        * 
      from 
        forecast_baseline

    INSERT INTO @results (
      [billing_date],
      [year],
      [type],
      [dollars],
      [units],
      [CC],
      [offering],
      [IntegratedReleasePlanNm],
      [ProjectId],
      [ProjectNm],
      [ModelEstimateId],
      [query],
      [ItemGroupId],
      CashflowType
      )
      SELECT 
        b.datetimemonth
        ,year([billing_date])
        ,'Baseline'
        ,[dollars]
        ,[units]
        ,CC
        ,[offering]
        ,'Baseline'
        ,'projected'
        ,'projected'
        ,'projected'
        ,'projected'
        ,'N/A'
        ,'N/A'
      FROM 
        forecast_baseline a inner join yearsinmonths b 
          on cast(year([billing_date]) as char(4))+ RIGHT('00' + CONVERT(VARCHAR,month([billing_date])), 2) = @monthkey
         and b.datetimemonth > [billing_date]
      return
  end

【问题讨论】:

是的,请提供代码 添加了代码。问题在于 forecast_baseline cte。它正在寻找一个参数,就像它没有将 @monthkey 识别为参数一样。我必须在那里有变量,因为这个 cte 从中提取的表太大而无法加载整个东西。性能会下降。 【参考方案1】:

错误是因为您将CTE 命名为函数名称。更改第二个CTE 名称:

...
 WHERE 
 DATEADD(month, @Interval, enddatetimemonth) < @EndTime
), 

forecast_baseline (
...

任何其他名字。

您还需要使用 UNION ALL 而不是在结果表中单独插入 2 次,因为您只有 1 种可能查询 CTE。不能多次查询CTE

【讨论】:

哇。接得好。我什至没有想到。它应该有....我在没有意识到的情况下递归。非常感谢!

以上是关于cte tsql 使用变量的主要内容,如果未能解决你的问题,请参考以下文章

关于TSql

在CTE sql的select语句中更新局部变量

TSQL 何时为存储过程中的变量(和表变量)分配内存

CTE、子查询、临时表或表变量之间是不是存在性能差异?

TSQL设置表变量的列值

简单的TSQL基础编程格式