Sql 如何在列中查找连续值
我被赋予这个任务,试图在一个有大量行的表中检测一些重复记录。该表由2个联接表组成。首先,我有:Sql 如何在列中查找连续值,sql,oracle,Sql,Oracle,我被赋予这个任务,试图在一个有大量行的表中检测一些重复记录。该表由2个联接表组成。首先,我有: select b.event_number_id, b.tenure_number_id, a.work_start_date, a.work_stop_date, a.amount from MTA.mta_sow_event a, mta_tenure_event_xref b where a.event_number_id = b.event_number_id 现在我们有了一张桌子。重复记
select
b.event_number_id, b.tenure_number_id, a.work_start_date, a.work_stop_date, a.amount
from
MTA.mta_sow_event a, mta_tenure_event_xref b
where
a.event_number_id = b.event_number_id
现在我们有了一张桌子。重复记录具有唯一的事件编号id,铰孔字段将包含相同的数据,因此如下所示:
| event_number_id | tenure_number_id | work_start_date | work_stop_date |amount|
|-----------------|-------------------|-----------------|----------------|------|
| 5532733 | 688203 | 01-SEP-14 | 25-SEP-14 | 5000 |
| 5532734 | 688203 | 01-SEP-14 | 25-SEP-14 | 5000 |
这是一个重复记录的例子。存在连续的事件编号id,其余所有列具有相同的信息。我们相信我们的系统已经创建了重复的事件一段时间了,但现在这种情况不应该发生,所以我想查询整个联接表,并找到任何包含数据完全相同但事件编号不同且连续的行的内容
到目前为止,我成功地进行了一个简单的查询,显示了所有具有相同信息的行,不包括event\u number\u id列:
select
b.tenure_number_id, a.work_start_date, a.work_stop_date, a.amount, count(*)
from
MTA.mta_sow_event a, mta_tenure_event_xref b
where
a.event_number_id = b.event_number_id
group by
b.tenure_number_id, a.work_start_date, a.work_stop_date, a.amount
having
count(*) > 1
返回:
| tenure_number_id | work_start_date | work_stop_date |amount|Count(*)|
|-------------------|-----------------|----------------|------|--------|
| 688203 | 01-SEP-14 | 25-SEP-14 | 5000 | 2 |
问题是,有时有些行具有相同的数据,但可能是有效的,因此,此时我们所能做的最好的事情就是找到任何具有连续事件编号id的匹配行。这就是我挂断电话的地方。有没有办法只提取包含这些连续数字的行?总体思路:将具有相同值的行分组,按任期编号id、工作开始日期、工作结束日期、金额、,使用分析函数min和row\u number从零开始查找每个组的最小事件编号\u id和组内事件编号\u id的行号,然后将最小id和行号之和与事件编号\u id进行比较。对于连续的数字,它们必须相等:
with t as (select b.event_number_id, b.tenure_number_id, a.work_start_date, a.work_stop_date, a.amount
from MTA.mta_sow_event a, mta_tenure_event_xref b
where a.event_number_id = b.event_number_id)
select *
from (select t.*,
min(event_number_id) over (partition by tenure_number_id, work_start_date, work_end_date, amount) +
row_number() over (partition by tenure_number_id, work_start_date, work_end_date, amount order by event_number_id) - 1 group_id
from t)
where event_number_id = group_id
您可以为此使用分析函数:
以下是一种基于数据集连接的方法:
with cte_base_data as (
select
... your query here ...)
select
from cte_base_data t1 join
cte_base_data t2 on (t1.tenure_number_id = t2.tenure_number_id and
t1.work_start_date = t2.work_start_date and
t1.work_stop_date = t2.work_stop_date and
t1.amount = t2.amount)
where t1.event_number_id = t2.event_number_id - 1;
效率将取决于几个因素,例如扫描基表的效率和数据集的大小
比较这种方法和分析功能方法的执行计划会很有趣。这种基于通用表表达式的连接应该非常有效,因为它依赖于哈希连接,只要它们留在内存中,几乎没有成本,这是一个很大的问号
如果事件编号id不是连续的,我倾向于使用分析函数——例如,如果可能存在间隙,这将更难作为连接实现。考虑到其中一个表是递增的,我认为值得在一个联接上下赌注。您显示的是对两个表的引用,而不是对一个表的引用。两个表中是否都有重复项?正如我所说,这是一个连接表。第一个表包含一些信息,但第二个表中的保留期\编号\ id列包含在内非常关键。问题是,我们每个任期都有重复的活动。我们采用的方法是找出连续事件是否具有相同的保留期编号、开始日期、结束日期和金额。没关系,您可以在一个查询中连接两个表,以投影所需的列,将其包装,并有效地将其视为您正在查询的表。我想有两种方法:1。找到重复的,然后检查它们是否有连续的数字,或2。查找连续的数字,然后确定它们是否重复。您可以从t开始作为原始查询选择*从…Dmitry开始,非常有趣!感谢您在入睡时如此专注于解决此问题:
with cte_base_data as (
select
... your query here ...)
select
from cte_base_data t1 join
cte_base_data t2 on (t1.tenure_number_id = t2.tenure_number_id and
t1.work_start_date = t2.work_start_date and
t1.work_stop_date = t2.work_stop_date and
t1.amount = t2.amount)
where t1.event_number_id = t2.event_number_id - 1;