2015-08-09 109 views
2

检查最小和最大的ID后,我需要从下表#a寻找失踪的id:的我需要找到从表中缺少ID从另一个表

id |SEQ|Text 
1 |1 |AA 
1 |3 |CC 
1 |4 |DD 
1 |5 |EE 
1 |6 |FF 
1 |7 |GG 
1 |8 |HH 
1 |10 |JJ 
2 |1 |KK 
2 |2 |LL 
2 |3 |MM 
2 |4 |NN 
2 |6 |PP 
2 |7 |QQ 
3 |1 |TT 
3 |4 |ZZ 
3 |5 |XX 

MAX和MIN SEQ表#a存储在另一个表#b:下面

id| mn| mx 
1 | 1 | 12 
2 | 1 | 9 
3 | 1 | 5 

我的查询给予正确的输出,但执行是昂贵的。有没有解决这个问题的另一种方法?

with cte 
as 
(
    select id, mn, mx 
    from #b 

    union all 

    select id, mn, mx -1 
    from cte 
    where mx-1 > 0 
) 
select 
    cte.id, cte.mx 
from 
    cte 
    left join #a on cte.id = #a.id and cte.mx = #a.seq 
where 
    #a.seq is null 
order by cte.id, cte.mx 

主要有在此查询2个问题:

  1. 查询运行速度非常慢。上述记录仅仅是一个例子。在真实的数据库中,我有50,000行。 enter image description here

  2. 我试着了解检测打嗝的执行计划。但是我无法理解它的某些部分,我在Red中已经强调了这一点。

如果有人能帮助我,这将是一件好事。我被卡住了。

回答

2

您使用递归CTE到generate a set of numbers。这样做效率相当低(参见生成50K号码的图表here)。我建议在数据库中有一个持久的数字表。我个人有一个表Numbers与100K行与一列Number,这是一个主键,它具有从1到100,000的整数。

一旦你这样的表,查询简化为这样的:

SELECT 
    #b.id, #b.mx 
FROM 
    #b 
    INNER JOIN Numbers ON 
     #b.mx >= Numbers.Number AND 
     #b.mn <= Numbers.Number -- use this clause if mn can be more than 1 
    LEFT JOIN #a ON 
     #a.id = #b.id AND 
     #a.seq = Numbers.Number 
WHERE 
    #a.seq IS NULL 
ORDER BY #b.id, #b.mx 

而且,不用说,你必须确保你在id#b有指标,再加上#a指数在(id, seq)

+0

谢谢你。它是从sys.all_objects生成数字的好方法。我将在明天上班时测试它的表现。但我确信这种方法会提高查询性能。再次感谢你的时间 – sam

+0

@sam,如果你有一个持久的数字表,它将有一个主键(唯一索引)。如果你想要表现,有一个索引是很重要的。 –

0

CTE只是语法和最有可能得到多次评估
物化为CTE输出到#TEMP并加入到#TEMP

1

两件事情,我想起有:

  • 使用数字/计数表。通过创建一个普通表或使用CTE创建一个虚拟表。用它来查找不存在的数字。

  • 如果不是很多丢失号码的,你可以使用与ROW_NUMBER()一招地发现,没有任何间隙的是这样的数字范围:

    select id, min(seq), max(seq) 
    from (
        select 
        id, 
        seq, 
        seq - row_number() over (partition by id order by SEQ asc) GRP 
        from 
        table1 
    ) X group by id, GRP 
    order by 1 
    

当您找到存在的数字范围后,这当然需要更多的处理。

+0

请问请详细说明row_number如何帮助您查找范围?我没有看到它可以帮助http://数据。stackexchange.com/stackoverflow/query/edit/345587 –

+0

@RoyiNamir你正在使用a进行分区,所以你的行号总是1,删除它。 –

+0

谢谢。你是对的。 PS如果'a'不是以'1'开头的话?我怎样才能_align_ row_number偏移量? –

相关问题