我有一个查询来显示两个日期之间员工的出勤状态。
将两个参数@FromDate
和@ToDate
传递给存储过程。此存储过程具有CTE,其中填充了此期间之间的所有日期。这在下面的查询中由T表示。另一个CTE,即TUI,保存T的所有日期以及来自另一个名为USER_INFO
的表的所有相关用户ID。
需要加入的其他表格是:
表:USER_INFO
USER_ID INT P.K, DISPLAY_NAME Varchar
表:ATTDETAILS
inUserID INT P.K, dtAttendanceDate DateTime, inAttendanceStatusId INT F.K
表:Att_Status_Master
inAttendanceStatusId INT P.K, ATTStatus VARCHAR
上面表AttStatus
中的列Att_Status_Master
包含值:Present, Absent
等。
以下代码的问题在于,只有在特定日期存在任何AttStatus
时才会提供结果。如果员工没有在特定日期标记出勤率,那么该日期不会出现在结果集中。
我希望显示所有日期,而不管NULL值如何。上面提到的CTE T将两个日期之间的所有日期提供给临时表#Results。现在我想向所有员工展示所有这些日期。
例如:
如上所示,日期01 / dec / 2012没有状态,但仍应显示在结果中。而使用以下查询,它不会显示。以下查询仅显示填充AttStatus
的记录。
最终存储过程代码如下:
@FromDate DateTime /* Input Parameter */
@ToDate DateTime /* Input Parameter */
If OBJECT_ID('tempdb..#Results',N'U') IS NOT NULL
DROP TABLE #Results
DECLARE @StartDate DateTime
DECLARE @EndDate DateTime
@StartDate = Convert(Varchar(25),@FromDate,112)
@EndDate = Convert(Varchar(25), (DateAdd(DAY,15,@FromDate)),112)
;With T (tempStoredDate)
AS (
select @StartDate
union all
select dateadd(day,1,tempStoredDate) from T where T.tempStoredDate < @EndDate
),
TUI AS
(
select T.tempStoredDate, UI.user_id, ui.display_name, dbo.GetEmployeeCode(UI.user_id) AS EmpCode from T
cross join user_info UI
)
select TUI.EmpCode, UI.user_id, UI.Display_Name, TUI.tempStoredDate, AD.dtAttendanceDate, ASM.AttStatus
INTO #Results From TUI
left outer join user_info UI
on TUI.user_id = UI.user_id
left outer join Att_Details AD
on UI.user_id = AD.inUserId
inner join Att_Status_Master ASM
on ASM.inAttendanceStatusId = AD.inAttendanceStatusId
where Convert(Varchar(25),dtAttendanceDate,112) = Convert(Varchar(25),tempStoredDate,112)
group by TUI.tempStoredDate,UI.user_id,UI.Display_Name,TUI.EmpCode,AD.dtAttendanceDate,AD.inAttendanceStatusId,ASM.AttStatus
我注意到,由于WHERE子句,这种情况正在发生。如果我忽略WHERE
子句,则所有日期都可见,但AttStatus
显示错误。
答案 0 :(得分:1)
您希望将WHERE子句中的条件移动到LEFT JOIN
From TUI
left join user_info UI on TUI.user_id = UI.user_id
left join Att_Details AD on UI.user_id = AD.inUserId
and Convert(Varchar(25),AD.dtAttendanceDate,112)
= Convert(Varchar(25),TUI.tempStoredDate,112) /* condition moved here */
join Att_Status_Master ASM
on ASM.inAttendanceStatusId = AD.inAttendanceStatusId
group by
TUI.tempStoredDate, UI.user_id, UI.Display_Name,
TUI.EmpCode, AD.dtAttendanceDate, AD.inAttendanceStatusId, ASM.AttStatus