如果存在于SQl Server中的CTE内

时间:2013-02-06 11:16:18

标签: sql sql-server-2008

我只想知道如何在SQl Server中编写包含CTE的{​​{1}}? 我曾尝试在下面写一个CTE,我正在使用If Exists语句选择天气记录是否存在。如果记录不存在,那么我分配默认值但是我收到错误

  

'关键字'if'

附近的语法不正确

“。请帮我解决这个错误并指导我写这个CTE。 请在下面找到我写过的CTE: -

If Exists

GO

当我删除这个If Exist语句时,Alter procedure St_Proc_GetTeamProductionReport @mindate DateTime, @maxdate DateTIme, @userID varchar(50) as Begin set NoCount on; with ProductionCTE(CalendarDate,RoleID,UserID,UserECode,UserName,ImmediateSupervisor,NatureOfWorkName,RegionProjectName,CountyName,WorkTypeName,TaskName,VolumneProcessed,TimeSpent,Comment) as ( if exists ( select P.CalendarDate,U.RoleID,U.UserID,U.UserECode,U.UserName,U.ImmediateSupervisor,N.NatureofWorkName, R.RegionProjectName,C.Countyname,W.WorktypeName,T.TaskName,P.VolumeProcessed,P.Timespent,P.Comment from production P inner join NatureOfWork N on N.NatureofWorkID=P.natureofworkid inner join dbo.RegionAndProjectInfo R on R.RegionProjectID=P.RegionProjectID inner join county C on C.countyid=P.countyid inner join worktype W on W.Worktypeid=P.worktypeID inner join task T on T.taskid=P.TaskID inner join UserInfo U on U.Userid=P.userid where P.userid=@userID and ( convert(varchar, P.CalendarDate, 101) ) between ( convert(varchar, @mindate, 101) ) and ( convert(varchar, @maxdate, 101) ) ) else ( Select '2012-09-14 13:41:52' as CalendarDate, 2 as RoleID,'938' as UserID, (select Userecode from Userinfo where userid=@userID) as UserECode, (select UserName from Userinfo where userid=@userID)as UserName, (select ImmediateSupervisor from Userinfo where userid=@userID)as ImmediateSupervisor, 'BP' as NatureOfWorkName, 'CO Processing' as RegionProjectName, 'Adams' as CountyName, 'Quality' as WorkTypeName, 'Corrections ' as TaskName, 5 as VolumneProcessed, '01:00' as TimeSpent, 'test' as Comment ) union all select P.CalendarDate,U.RoleID,U.UserID,U.UserECode,U.UserName,U.ImmediateSupervisor,N.NatureofWorkName, R.RegionProjectName,C.Countyname,W.WorktypeName,T.TaskName,P.VolumeProcessed,P.Timespent,P.Comment from production P inner join NatureOfWork N on N.NatureofWorkID=P.natureofworkid inner join dbo.RegionAndProjectInfo R on R.RegionProjectID=P.RegionProjectID inner join county C on C.countyid=P.countyid inner join worktype W on W.Worktypeid=P.worktypeID inner join task T on T.taskid=P.TaskID inner join UserInfo U on U.Userid=P.userid inner join ProductionCTE on U.ImmediateSupervisor=ProductionCTE.UserECode where P.IsTaskCompleted=1 and ( convert(varchar, P.CalendarDate, 101) ) between ( convert(varchar, @mindate, 101) ) and ( convert(varchar, @maxdate, 101) ) ) select distinct CONVERT(VARCHAR,CalendarDate,20) as CalendarDate,UserECode,UserName,NatureOfWorkName,RegionProjectName,CountyName,WorkTypeName,TaskName,VolumneProcessed,TimeSpent,Comment from ProductionCTE where RoleID=1 end 工作正常,但在添加CTE语句后,它有错误。

4 个答案:

答案 0 :(得分:2)

您不能以这种方式使用IF EXISTS。公用表表达式只能包含一个select语句,不能说if condition SELECT THIS else SELECT THAT

看起来您正在尝试将其他创建的行添加到查询返回的结果集中。您可以通过将CTE实现为将返回单个新行的表值函数来实现此目的。

http://msdn.microsoft.com/en-gb/library/ms191165(v=sql.105).aspx

答案 1 :(得分:1)

如果您要构建UNION,只有第一个SELECT没有返回任何行,您才能从第二个SELECT获得结果,您可以使用RANK()来实现此目的。因此,您可以将真实查询放在第一个SELECT中,将所需的默认值放在第二个中,然后获得所需的结果。

我没有你的表和数据,所以我不会尝试重新编写你的查询。但我会用这个来说明:

;With WithDefaults as (
    select name,0 as Rank from sys.objects
    union all
    select 'abc',1 --Default if no results
), Ranked as (
    select *,RANK() OVER (ORDER BY Rank) as Rnk from WithDefaults
)
select * from Ranked where Rnk = 1

返回(在我尝试过的大多数空DB上)98个结果,其中没有name abc。如果我们强制第一个SELECT没有返回结果:

    select name,0 as Rank from sys.objects where 1 = 2

我们现在使用name abc获得单行结果。

希望你能看到这对你的原始查询有什么用。

答案 2 :(得分:0)

您不能在CTE中使用IF EXISTS。但是你可以修改函数逻辑

示例:

alter procedure St_Proc_GetTeamProductionReport
@mindate DateTime,                        
@maxdate DateTIme,    
@userID varchar(50)                    
as                                          
Begin                                          
set NoCount on;
;with    
ProductionCTE(CalendarDate,RoleID,UserID,UserECode,UserName,ImmediateSupervisor,NatureOfWorkName,RegionProjectName,CountyName,WorkTypeName,TaskName,VolumneProcessed,TimeSpent,Comment)    
as    
(               
        select P.CalendarDate,U.RoleID,U.UserID,U.UserECode,U.UserName,U.ImmediateSupervisor,N.NatureofWorkName,    
        R.RegionProjectName,C.Countyname,W.WorktypeName,T.TaskName,P.VolumeProcessed,P.Timespent,P.Comment, 1 AS cnt 
        from production P inner join NatureOfWork N    
        on N.NatureofWorkID=P.natureofworkid    
        inner join dbo.RegionAndProjectInfo R    
        on R.RegionProjectID=P.RegionProjectID    
        inner join county C    
        on C.countyid=P.countyid    
        inner join worktype W    
        on W.Worktypeid=P.worktypeID    
        inner join task T    
        on T.taskid=P.TaskID    
        inner join UserInfo U    
        on U.Userid=P.userid    
        where P.userid=@userID  and ( convert(varchar, P.CalendarDate, 101) )  between (
        convert(varchar, @mindate, 101) ) and ( convert(varchar, @maxdate, 101) )  
        UNION ALL
        Select '2012-09-14 13:41:52' as CalendarDate,
        2 as RoleID,'938' as UserID,
        (select Userecode from Userinfo where userid=@userID) as UserECode,
        (select UserName from Userinfo where userid=@userID)as UserName,
        (select ImmediateSupervisor from Userinfo where userid=@userID)as ImmediateSupervisor,
        'BP' as NatureOfWorkName,
        'CO Processing' as RegionProjectName,
        'Adams' as CountyName,
        'Quality' as WorkTypeName,
        'Corrections ' as TaskName,
        5 as VolumneProcessed,
        '01:00' as TimeSpent,
        'test' as Comment, 0 
     ), ProductionCTE2 AS    
    (    
    SELECT TOP(SELECT CASE WHEN COUNT(*) = 0 THEN 1 ELSE COUNT(*) END FROM ProductionCTE WHERE cnt = 1)
           CalendarDate,RoleID,UserID,UserECode,UserName,ImmediateSupervisor,NatureofWorkName,    
           RegionProjectName,Countyname,WorktypeName,TaskName,VolumeProcessed,Timespent,Comment
    FROM ProductionCTE2           
    union all
    select P.CalendarDate,U.RoleID,U.UserID,U.UserECode,U.UserName,U.ImmediateSupervisor,N.NatureofWorkName,    
    R.RegionProjectName,C.Countyname,W.WorktypeName,T.TaskName,P.VolumeProcessed,P.Timespent,P.Comment    
    from production P inner join NatureOfWork N    
    on N.NatureofWorkID=P.natureofworkid    
    inner join dbo.RegionAndProjectInfo R    
    on R.RegionProjectID=P.RegionProjectID    
    inner join county C    
    on C.countyid=P.countyid    
    inner join worktype W    
    on W.Worktypeid=P.worktypeID    
    inner join task T    
    on T.taskid=P.TaskID    
    inner join UserInfo U    
    on U.Userid=P.userid    
    inner join ProductionCTE    
    on U.ImmediateSupervisor=ProductionCTE.UserECode
    where P.IsTaskCompleted=1   and ( convert(varchar, P.CalendarDate, 101) )  between (
    convert(varchar, @mindate, 101) ) and ( convert(varchar, @maxdate, 101) )         
)  
select  distinct CONVERT(VARCHAR,CalendarDate,20) as CalendarDate,UserECode,UserName,NatureOfWorkName,RegionProjectName,CountyName,WorkTypeName,TaskName,VolumneProcessed,TimeSpent,Comment 
from ProductionCTE2
where  RoleID=1    
end

答案 3 :(得分:-1)

进出CTE

If Exists(some select statement)
  DoSomething
else
  DoSomethingElse

你错过了dosomething位