Dharmendra Kumar Singh
Dharmendra Kumar Singh

Reputation: 2991

If Exists inside a CTE in SQl Server

I just want to know that How to write a CTE containing If Exists in SQl Server ? I had tried to write a CTE below where i am Using If Exists Statement to select weather the record exist or not .In case if the record does not exist then i am assigning default value but i am getting error

'Incorrect syntax near the keyword 'if'

.' Please help me to fix this error and guide me to write this CTE. Please find below the CTE which i had written:-

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

GO

When i am removing this If Exist statement then the CTE is working fine but after adding the IF Exists statement it is having error.

Upvotes: 2

Views: 7801

Answers (3)

Oleksandr Fedorenko
Oleksandr Fedorenko

Reputation: 16904

You can't use IF EXISTS in CTE. But you can modify logic of function

Example:

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

Upvotes: 0

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239654

If you want to construct a UNION where you only get a result from the second SELECT if the first SELECT returns no rows, you can achieve this using RANK(). So, you can place your real query in the first SELECT and the desired default values in the second, and achieve the results you want.

I don't have your tables and data, so I'm not going to attempt to re-write your query. But I'll illustrate with this:

;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

Returns (on a mostly empty DB I tried it on) 98 results, of which none had the name abc. If we force the first SELECT to return no results:

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

We now get a single row result with the name abc.

Hopefully, you can see how this could apply to your original query.

Upvotes: 1

paul
paul

Reputation: 22001

You can't use IF EXISTS in this way. A common table expression must only contain a single select statement, it's not possible to say if condition SELECT THIS else SELECT THAT.

It looks like you are trying to add an additional created row to a resultset returned by a query. You could achieve this by implementing the CTE as a table-valued function that would return the single new row.

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

Upvotes: 2

Related Questions