sql 中两个表的 Start_date 不匹配的查询

Query in which Start_date of two tables do not match in sql

我有两张桌子 per_asgxx_asg,它们的编号相同。的列,理想情况下应该有相同的编号。数据。

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 上看到的那样,有一个额外的行 start_date '03-feb-2016' 和 end_date '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

但这仍然是整个数据集

如果您想要额外的行,我希望查询更像这样:

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
                 );

如果如示例所示,两个表中的行逐个字段相等,您可以这样做:

 select * from xx_per_asg
  minus
 select * from per_asg

如果每个 table 可能有其他 table 中没有的行,并且您需要找到这两种类型,那么这样的方法应该可行。假设 table 都没有重复行(例如,如果它们每个都有主键,那将是正确的),那么如果您对两个 table 执行 union all,那么行存在于两个 table 中将在联合中重复。那些不在两个 table 中的将不会被复制。因此,在 union all 之后,我们可以按所有列分组并使用 HAVING COUNT(*) = 1 条件来查找仅在一个 table 中但不在另一个

中的行。

对此的一个小调整也将告诉我们哪个 table 有 "unpaired" 行,对于每一行。在解决方案中,我使用max(source)(因为我们不应该按"source"分组,所以我们需要在其上使用聚合函数),但它实际上是对单个值的max() ;它就是那个值。

这个解决方案是有效的,因为它不使用连接并且不使用昂贵的 MINUS 操作(或者,实际上,两个 MINUS 操作并且还读取每个 table两次而不是一次,如果分配是从两个 table 中找到不成对的行,而不仅仅是从一个)。

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 进行比较,则必须确保所有日期都是 "pure dates"(没有时间部分);也就是说,时间分量应该是00:00:00。是这样吗?如果不是,则所有解决方案都需要调整(并且效率会降低,也就是更耗时)。

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