如何使用右键连接从Right表中获取所有记录?

时间:2019-04-12 07:30:56

标签: sql sql-server

我正在生成每月出勤报告表,在其中我可以获取您在某天标记为出勤的那些员工的记录。这是我面临的问题,我需要报表中列出的每个员工,无论他的记录是否存在于出勤表中。

我使用了正确的外部联接,但id不适用于我,我环顾了其他解决方案,但没有人解决我的问题

Declare @fkSerial   [numeric]=0;
Declare @attDateTime [datetime]='2019-04-01';
Declare @Company nvarchar(50)='ZCG';
Declare @Department nvarchar(50)=null;
Declare @StartOfMonth Datetime
Declare @EndOfMonth Datetime
declare @month int
declare @year int
declare @day int
set @month =DATEPART(month, @attDateTime)
set @year =DATEPART(year, @attDateTime)
set @day =DATEPART(day, @attDateTime)
set @StartOfMonth = DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)
set @EndOfMonth =  dateadd(SECOND,-1,DATEADD(MONTH,datediff(MONTH,0,GETDATE())+1,0));
With DATERANGE  as(
SELECT DT =DATEADD(DD,0,@StartOfMonth)  
       WHERE DATEADD(DD, 1,@StartOfMonth) <=@EndOfMonth 
       UNION ALL  
       SELECT DATEADD(DD, 1, DT)  
       FROM DATERANGE  
       WHERE DATEADD(DD, 1, DT) <=@EndOfMonth 

)

SELECT fkSerial,company,serial, 
 name,department,attINOUT,[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30]
FROM 
(SELECT Day(attDateTime) as d1,fkSerial,attDateTime, tblEmployInfo.company,  tblEmployInfo.serial, tblAttendance.attINOUT,
 tblEmployInfo.name,tblEmployInfo.department
FROM tblAttendance RIGHT outer JOIN
    tblEmployInfo ON tblAttendance.fkSerial = tblEmployInfo.serial
where(     
(tblAttendance.fkSerial = @fkSerial  OR @fkSerial  = 0) AND 
(tblEmployInfo.department = @Department OR @Department is null) And 
(tblAttendance.attDate in (select * from DATERANGE)) and 
(tblEmployInfo.company= @Company or  @Company is null)
and tblAttendance.attINOUT=0
)
group by  tblAttendance.attDateTime,tblAttendance.fkSerial,tblEmployInfo.company,tblEmployInfo.serial,tblAttendance.attINOUT,tblEmployInfo.name,tblEmployInfo.department
having tblAttendance.attDateTime= min(tblAttendance.attDateTime)

) p
PIVOT(
MAx(p.attDateTime)
FOR d1 IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30] ) ) AS pvt
ORDER BY 
pvt.fkSerial

我需要报告中列出的每个员工,无论他的记录是否存在于出勤表中

2 个答案:

答案 0 :(得分:0)

您的WHERE状况有问题。您已指定tblAttendance.attINOUT = 0,而tblAttendance是您的左表,仅当左表中有记录时,该表才为true。因此,它会破坏您的RIGHT OUTER JOIN的目的。

尝试用ISNULL(tblAttendance.attINOUT,1)= 0替换tblAttendance.attINOUT = 0,然后查看是否获得所需的结果。希望这对您有所帮助:)。

答案 1 :(得分:0)

无论联接方向如何,辅助表字段(在这种情况下为tblAttendance)上的所有条件都必须位于联接(ON子句)中,而不位于where中。只有路口的记录将具有相等的条件,并且结果将与INNER JOIN相同。如果存在可空字段,则添加OR IS NULL条件并不总是准确的。

SELECT Day(attDateTime) as d1,fkSerial,attDateTime, tblEmployInfo.company,  tblEmployInfo.serial, tblAttendance.attINOUT,
 tblEmployInfo.name,tblEmployInfo.department
FROM tblAttendance 
RIGHT OUTER JOIN tblEmployInfo 
    ON tblAttendance.fkSerial = tblEmployInfo.serial
    AND (     
        (tblAttendance.fkSerial = @fkSerial  OR @fkSerial  = 0) AND     
        (tblAttendance.attDate in (select * from DATERANGE)) AND
        tblAttendance.attINOUT=0
    )
WHERE
    (tblEmployInfo.department = @Department OR @Department is null) 
    AND (tblEmployInfo.company= @Company or  @Company is null)

此外,我想更改表的顺序并改用LEFT JOIN,我认为这是更标准的选择,但这是您的选择

SELECT Day(attDateTime) as d1,fkSerial,attDateTime, tblEmployInfo.company,  tblEmployInfo.serial, tblAttendance.attINOUT,
     tblEmployInfo.name,tblEmployInfo.department
    FROM tblEmployInfo 
    LEFT JOIN tblAttendance  
        ON tblAttendance.fkSerial = tblEmployInfo.serial
        AND (     
            (tblAttendance.fkSerial = @fkSerial  OR @fkSerial  = 0) AND     
            (tblAttendance.attDate in (select * from DATERANGE)) AND
            tblAttendance.attINOUT=0
        )
    WHERE
        (tblEmployInfo.department = @Department OR @Department is null) 
        AND (tblEmployInfo.company= @Company or  @Company is null)