繁体   English   中英

在数字序列中查找错过的最大值和最小值

[英]Find missed max and min value in a sequence of numbers

例如,我有一个数字序列: {1, 2, 5, 7} 我需要找到最小和最大的,这在这个序列中被遗漏了(这个例子中 min=3 和 max=6)。 值也可以是负数。 这是我的解决方案,但它没有传递额外的检查数据库(错误的记录数(减去 1)),所以我不能说到底是什么错误。 我还尝试了带有 LEFT OUTER JOIN 和 EXCEPT 谓词的版本——同样的问题。 请帮助我改进我的解决方案。

WITH AA AS (SELECT MAX(Q_ID) MX
            FROM UTQ),
   
     BB AS (SELECT MIN(Q_ID) CODE
            FROM UTQ
            
            UNION ALL
            
            SELECT CODE + 1
            FROM BB
            WHERE CODE < (SELECT MX
                          FROM AA)
            )

SELECT MIN(CODE) MIN_RES, MAX(CODE) MAX_RES
FROM BB
WHERE CODE NOT IN (SELECT Q_ID
                   FROM UTQ)

一种方法not exists

select min(q_id + 1)
from utq
where not exists (select 1 from utq utq2 where utq2.q_id = utq.id + 1)
union all
select max(q_id - 1)
from utq
where not exists (select 1 from utq utq2 where utq2.q_id = utq.id - 1);

您还可以使用lead()lag()

select min(case when next_q_id <> q_id + 1 then q_id + 1 end),
       max(case when prev_q_id <> q_id - 1 then q_id - 1 end)
from (select utq.*,
             lag(q_id) over (order by q_id) as prev_q_id,
             lead(q_id) over (order by q_id) as next_q_id
      from utq
     ) utq;

基于计数的方法在这里似乎是一个好方法。 特别是如果序列很大。

第一个CTE总结了测试表中的最大和最小 q_id。 第二个CTE通过生成最小和最大 q_id 值之间的完整序列(使用 fnNumbers tvf)并将WHERE NOT EXISTS与原始序列进行比较来选择缺失的整数。 像这样的东西。

数字 function

create function [dbo].[fnNumbers](
  @zero_or_one   bit, 
  @n             bigint)
returns table with schemabinding as return
with n(n) as (select null from (values (1),(2),(3),(4)) n(n))
select 0 n where @zero_or_one = 0
union all
select top(@n) row_number() over(order by (select null)) n
from n na, n nb, n nc, n nd, n ne, n nf, n ng, n nh,
     n ni, n nj, n nk, n nl, n nm, n np, n nq, n nr;

数据和查询

drop table if exists #seq;
go
create table #seq(
  q_id          int unique not null);

insert #seq values (1),(2),(5),(7);

with
max_min_cte(max_q, min_q) as (
    select max(q_id), min(q_id)
    from #seq),
missing_cte(q_id) as (
    select mm.min_q+fn.n
    from max_min_cte mm
         cross apply dbo.fnNumbers(0, mm.max_q-mm.min_q) fn
    where not exists (select 1
                      from #seq s
                      where (mm.min_q+fn.n)=s.q_id))
select max(q_id) max_missing, min(q_id) min_missing
from missing_cte;

output

max_missing min_missing
6           3

您可以尝试使用LEAD

SELECT MIN(Q_ID + 1) AS MinValue
      ,MAX(Q_ID + 1) AS MaxValue
FROM (
    SELECT *,LEAD(Q_ID) OVER (ORDER BY Q_ID) NQ_ID
    FROM (VALUES (1),(2),(5),(7)) v(Q_ID)
    ) t
WHERE NQ_ID - Q_ID <> 1

暂无
暂无

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

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