TSQL CTE错误:')附近的语法不正确

时间:2011-12-01 15:02:33

标签: tsql common-table-expression sql-server-2008

我正在使用SSMS 2008开发TSQL存储过程,并在生成CTE时收到上述错误。我想为此SP添加逻辑以返回每天,而不仅仅是数据的日子。我该怎么做呢?到目前为止,这是我的SP:

ALTER Proc [dbo].[rpt_rd_CensusWithChart]
   @program uniqueidentifier = NULL,
   @office uniqueidentifier = NULL
AS
DECLARE @a_date datetime
SET @a_date = case when MONTH(GETDATE()) >= 7 THEN '7/1/' + CAST(YEAR(GETDATE()) AS VARCHAR(30))
ELSE '7/1/' + CAST(YEAR(GETDATE())-1 AS VARCHAR(30)) END

if exists (
    select  * from tempdb.dbo.sysobjects o    where o.xtype in ('U')  and o.id = object_id(N'tempdb..#ENROLLEES')
) DROP TABLE #ENROLLEES;
if exists (
    select  * from tempdb.dbo.sysobjects o    where o.xtype in ('U')  and o.id = object_id(N'tempdb..#DISCHARGES')
) DROP TABLE #DISCHARGES;

declare @sum_enrollment int

set @sum_enrollment =  
(select sum(1)
from enrollment_view A
join enrollment_info_expanded_view C on A.enrollment_id = C.enroll_el_id 
where
   (@office is NULL OR A.group_profile_id = @office)

   AND (@program is NULL OR A.program_info_id = @program)
and (C.pe_end_date IS NULL OR C.pe_end_date > @a_date)
AND C.pe_start_date IS NOT NULL and C.pe_start_date < @a_date)

select 
A.program_info_id as [Program code], 
A.[program_name],
A.profile_name as Facility, 
A.group_profile_id as Facility_code, 
A.people_id, 
1 as enrollment_id,

C.pe_start_date,
C.pe_end_date,
LEFT(datename(month,(C.pe_start_date)),3) as a_month,
day(C.pe_start_date) as a_day,
@sum_enrollment as sum_enrollment

into #ENROLLEES
from enrollment_view A
join enrollment_info_expanded_view C on A.enrollment_id = C.enroll_el_id 
where
   (@office is NULL OR A.group_profile_id = @office)
   AND (@program is NULL OR A.program_info_id = @program)
and (C.pe_end_date IS NULL OR C.pe_end_date > @a_date)

AND C.pe_start_date IS NOT NULL and C.pe_start_date >= @a_date

;WITH #ENROLLEES AS (
    SELECT '7/1/11' AS dt
    UNION ALL
    SELECT DATEADD(d, 1, pe_start_date) as dt
      FROM #ENROLLEES s
     WHERE DATEADD(d, 1, pe_start_date) <= '12/1/11')

1 个答案:

答案 0 :(得分:5)

最明显的问题(也可能是导致错误消息的问题)是缺少最后一个CTE应该属于的实际语句。我认为它应该是一个SELECT语句,它将CTE的结果集与#ENROLLEES表中的数据结合起来。

这就是另一个问题出现的地方。

你知道,除了一个以单#开头的名字对于任何不是本地临时表(CTE确实不是表格)的东西都是不可取的,你也选择了对于您的CTE,已经属于现有表的特定名称(更准确地说,属于已经提到的#ENROLLEES临时表),以及您要从中提取数据的名称。您绝对不应该使用CTE的现有表名,否则由于名称冲突,您将无法将其与CTE连接。

根据其代码,最后的CTE似乎表示您想要添加到SP的逻辑的未完成实现。我可以提出一些想法,但在我继续之前,我想让你意识到你的帖子中实际上有两个不同的请求。一个是找到错误消息的原因,另一个是关于新逻辑的代码。一般来说,将这些请求分成不同的问题可能会更好,所以你也可能会遇到这种情况。

无论如何,这是我的建议:

  • 在结果集中构建一个完整的日期列表(这就是CTE的用途);

  • 使用#ENROLLEES表左键加入该列表,以选择现有日期的数据,并为不存在的日期选择一些默认值或NULL。

可能会这样实现:

… /* all your code up until the last WITH */
;
WITH cte AS (
  SELECT CAST('7/1/11' AS date) AS dt
  UNION ALL
  SELECT DATEADD(d, 1, dt) as dt
  FROM cte
  WHERE dt < '12/1/11'
)
SELECT
  cte.dt,
  tmp.[Program code],
  tmp.[program_name],
  … /* other columns as necessary; you might also consider
       enveloping some or all of the "tmp" columns in ISNULLs,
       like in

         ISNULL(tmp.[Program code], '(none)') AS [Program code]

       to provide default values for absent data */
FROM cte
  LEFT JOIN #ENROLLEES tmp ON cte.dt = tmp.pe_start_date
;