繁体   English   中英

在检查另一个表的最小和最大ID之后,我需要从表中找到丢失的ID

[英]I need to find the missing Id's from the table after checking the min and max id's from another table

我需要从下表#a中找到丢失的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

#a的最大和最小SEQ存储在另一个表#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行。 在此处输入图片说明

  2. 我试图了解执行计划以检测出打ic。 但是,我无法理解其中的某些内容,在红色中已对此进行了突出显示。

如果有人可以在这里帮助我,那将是很棒的。 我被困住了。

您使用递归CTE 生成一组数字 这是一种非常低效的方法(请参阅此处的生成50K数字的图表)。 我建议在数据库中保留一个数字表。 我个人有一个表Numbers ,其中有10万行,其中一列是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上有索引,在(id, seq)上的#a上有索引。

我想到的两件事是:

  • 使用数字/理货表格。 通过创建普通表或使用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 

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

CTE只是语法,很可能会被多次评估
将CTE输出具体化为#temp并加入#temp

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM