sql 中两个表的 Start_date 不匹配的查询
Query in which Start_date of two tables do not match in sql
我有两张桌子 per_asg
和 xx_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
我有两张桌子 per_asg
和 xx_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