我有两张桌子(来自两个不同的系统)跟踪员工的情况。小时。在两个表中,员工输入日期和小时。我需要创建一个显示差异的审计报告。报告需要显示所有列,如果存在不匹配,则显示空/不匹配。一个表可能有比其他表更多/更少的条目,甚至重复条目,我需要捕获它(同一天两个条目在一个表中相同的小时数)。两个表都有可以连接的UserID。
如果根据日期和时间匹配,则显示所有值。 如果基于小时数不匹配,则在不匹配时显示null或不匹配。 如果有重复的条目,如下图所示,则匹配第一个条目并将第二个条目报告为空或不匹配。
我尝试根据UserID,日期和小时加入表格,但无法分辨出不匹配的来源。
表A:
表B:
左边加入UserID,日期和小时
答案 0 :(得分:1)
SET NOCOUNT ON;
declare @table1 table
(
userid int,
entry_date date,
[hours] varchar(10)
)
declare @table2 table
(
userid int,
entry_date datetime,
[hours] varchar(10)
)
INSERT INTO @table1
select 1,'8/14/2017','10:00'
INSERT INTO @table1
select 2,'8/14/2017','5:00'
INSERT INTO @table1
select 2,'8/14/2017','5:00'
INSERT INTO @table1
select 2,'8/14/2017','5:00'
INSERT INTO @table1
select 2,'8/14/2017','5:00'
INSERT INTO @table1
select 3,'8/14/2017','5:00'
INSERT INTO @table1
select 3,'8/14/2017','6:00'
INSERT INTO @table1
select 3,'8/14/2017','6:00'
INSERT INTO @table1
select 3,'8/14/2017','6:00'
INSERT INTO @table2
select 1,'8/14/2017','10:00'
INSERT INTO @table2
select 2,'8/14/2017','8:00'
INSERT INTO @table2
select 3,'8/14/2017','6:00'
INSERT INTO @table2
select 4,'8/14/2017','2:00'
INSERT INTO @table2
select 1,'8/14/2017','10:00'
INSERT INTO @table2
select 3,'8/14/2017','6:00'
;WITH CTE_TABLE1 AS
(
select t.userid as userid, CAST(t.entry_date as DATE) as entry_date, t.[hours] as [hours],
ROW_NUMBER() OVER(PARTITION BY t.userid, t.entry_date, t.[hours] ORDER BY t.[Hours]) as rnk
from @Table1 t
), CTE_TABLE2 AS
(
select t.userid as userid, CAST(t.entry_date as DATE) as entry_date, t.[hours] as [hours],
ROW_NUMBER() OVER(PARTITION BY t.userid, t.entry_date, t.[hours] ORDER BY t.[Hours]) as rnk
from @Table2 t
), CTE_MATCHES AS
(
select t1.userid as userid, t1.entry_date as entry_date, t1.[hours] as [hours], t1.rnk
from CTE_TABLE1 t1
inner join CTE_TABLE2 t2
on (t1.userid = t2.userid AND t1.entry_date = t2.entry_date AND t1.[hours] = t2.[hours] AND t1.rnk = t2.rnk)
),CTE_MATCH_DUPLICATES AS
(
select 'Table1MatchDuplicate' as ErrorType, *
from
(
select t.*
from (select userid, entry_date, [hours], max(rnk) as rnk from CTE_MATCHES group by userid, entry_date, [hours]) m
inner join CTE_TABLE1 t
on (t.userid = m.userid AND t.entry_date = m.entry_date AND t.[hours] = m.[hours] AND t.rnk > m.rnk)
)q
UNION ALL
select 'Table2MatchDuplicate' as ErrorType, *
from
(
select t.*
from (select userid, entry_date, [hours], max(rnk) as rnk from CTE_MATCHES group by userid, entry_date, [hours]) m
inner join CTE_TABLE2 t
on (t.userid = m.userid AND t.entry_date = m.entry_date AND t.[hours] = m.[hours] AND t.rnk > m.rnk)
)q
)
, CTE_Table1_UNMATCHED AS
(
select t.userid, t.entry_date, t.[hours]
from @Table1 t
left outer join CTE_MATCHES m
on (t.userid = m.userid AND CAST(t.entry_date as DATE) = m.entry_date AND t.[hours] = m.[hours])
where m.userid is null
), CTE_Table2_UNMATCHED AS
(
select t.userid, t.entry_date, t.[hours]
from @Table2 t
left outer join CTE_MATCHES m
on (t.userid = m.userid AND CAST(t.entry_date as DATE) = m.entry_date AND t.[hours] = m.[hours])
where m.userid is null
)
select null as ErrorType, userid, entry_date, [hours] from CTE_MATCHES
UNION ALL
select 'Table1Mismatch' as ErrorType, userid, entry_date, [hours] from CTE_Table1_UNMATCHED
UNION ALL
select 'Table2Mismatch' as ErrorType, userid, entry_date, [hours] from CTE_Table2_UNMATCHED
UNION ALL
select ErrorType, userid, entry_date, [hours] from CTE_MATCH_DUPLICATES
order by ErrorType
如果您需要查找没有匹配项的重复项:
,CTE_Table1_Unmatched_Duplicates AS
(
select userid, entry_date, [hours]
from CTE_Table1_UNMATCHED
group by userid, entry_date, [hours]
having count(*) > 1
),CTE_Table2_Unmatched_Duplicates AS
(
select userid, entry_date, [hours]
from CTE_Table2_UNMATCHED
group by userid, entry_date, [hours]
having count(*) > 1
)
...
UNION
select 'Table1UnmatchedDuplicates' as ErrorType, userid, entry_date, [hours] from CTE_Table1_Unmatched_Duplicates
UNION
select 'Table2UnmatchedDuplicates' as ErrorType, userid, entry_date, [hours] from CTE_Table2_Unmatched_Duplicates