2016-10-22 54 views
0

我有两个表per_asgxx_asg,它们有相同的no。列,理想情况下应该有相同的号码。数据的。查询两个表的Start_date在sql中不匹配

per_asg

person_id start_date end_date 
------------------------------------------- 
1   01-jan-2016 07-jan-2016 
1   02-feb-2016 08-march-2016 

xx_per_asg

person_id start_date end_date 
------------------------------------- 
1   01-jan-2016 07-jan-2016 
1   02-feb-2016 08-march-2016 
1   03-feb-2016 04-sep-2016 

由于看到xx_per_asg有一个额外的行与起始日期'03-feb-2016'日期和结束日期'04-sep-2016'.我写了一个查询来获取这样的行,但我我没有完全得到额外的行:

select start_date 
from xx_per_asg xx_per_asg, per_asg pa 
where xx_per_asg.person_id = pa.person_id 
    and xx_per_asg.start_date <> pa.start_date 

但是,这仍然会数据

+0

[不良习惯踢:使用旧式JOIN](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using-old -style-joins.aspx) - 在ANSI - ** 92 ** SQL标准中,旧式*逗号分隔的表*样式列表已替换为* proper * ANSI'JOIN'语法(**超过20年**前),其使用是不鼓励 –

回答

1

如果每个表可能有未在其他表中的行,你需要找到这两种,这样的事情寿ld工作。假设这两个表都没有重复的行(例如,如果它们每个都有主键,情况会是这样),那么如果您执行两个表中的一个union all,则两个表中存在的行将在联合中重复。那些不在两个表中的将不会被复制。因此,在union all之后,我们可以按所有列进行分组,并使用HAVING COUNT(*) = 1条件查找仅在一个表中但在另一个表中不存在的行。

对此的小调整也会告诉我们哪个表具有“未配对”行,对于每行。在解决方案中,我使用了max(source)(因为我们不应该按“源”进行分组,所以我们需要对它使用一个聚合函数),但它实际上是一个单一值的max();它只是那个价值。

此解决方案效率很高,因为它不使用联接,并且它不使用昂贵的操作(或实际上两个MINUS操作,并且每次读取每个表两次而不是一次,如果分配是查找未配对的行来自两个表格,而不仅仅是一个)。

select max(source), person_id, start_date, end_date 
from (select 'per_asg' as source, person_id, start_date, end_date from per_asg 
     union all 
     select 'xx_per_asg' as source, person_id, start_date, end_date from xx_per_asg 
     ) 
group by person_id, start_date, end_date 
having count(*) = 1 
order by person_id, start_date, end_date -- ORDER BY is optional 
; 

一两件事 - 如果你通过start_date比较,你必须确保所有的日期是“纯日期”(与时间的天没有分量);即时间分量应该是00:00:00。是这样吗?如果不是,所有解决方案都需要进行调整(并且效率会降低,这会花费更多时间)。

2

的整套如果你想额外行,我希望查询更多这样的:

select xx.* 
from xx_per_asg xx 
where not exists (select 1 
        from per_asg pa 
        where pa.person_id = xx.person_id and 
         pa.start_date = xx.start_date 
       ); 
0

如果,因为它似乎在这个例子中,这两个表中的行是相等的,由场场,你可以这样做:

select * from xx_per_asg 
    minus 
select * from per_asg 
0
Select xx.startdate,xx.enddate,xx.person_id from xx_per_asg xx 
LEFT OUTER JOIN per_asg per on per.person_id = xx.person_id 
Where xx.start_date <> per.start_date 
+0

我不知道这会工作。如果您在表t1和t2上有两行的日期为D1和D2,则它们将在结果集中显示为t1.D1 <> t2.D2和t2.D1 <> t1.D2。 – Insac