找到oracle中的最小缺失数量

时间:2017-04-01 10:34:54

标签: sql oracle

我想在oracle中找到名为(s_no)的列和名为(test_table)的表的最小缺失编号,并编写以下代码。

select 
    min_s_no-1+level missing_number 
from (
    select min(s_no) min_s_no, max(s_no) max_s_no 
    from test_table
) connect by level <= max_s_no-min_s_no+1
minus
select s_no from test_table
;

它为我提供了所有缺失的数字。但我想选择最低限度 数。任何人都可以帮助我。 提前谢谢。

3 个答案:

答案 0 :(得分:2)

使用分析函数LEAD,您可以按升序获得下一行中的数字。比较此值与原始数字增加1 ,您将获得缺失值(如果两个数字不匹配)。

要按升序获取第一个缺失值,请选择MIN值:

select 
num,
lead(num) over (order by num)  num_lead,
case when num + 1 != lead(num) over (order by num)  then num + 1 end as  missing_num
from test_data
order by num; 

       NUM   NUM_LEAD MISSING_NUM
---------- ---------- -----------
         4          5             
         5          6             
         6          9           7 
         9         10             
        10         13          11 
        13                        


-- first missing number = MIN missing number
select min(missing_num)
from (
select 
case when num + 1 != lead(num) over (order by num)  then num + 1 end as  missing_num
from test_data
);

MIN(MISSING_NUM)
----------------
               7 

<强>附录

编写SQL的一个好习惯是考虑边缘情况 - 这里是一个包含没有孔的完整间隔的表。第一个缺失值将是最后一个数字的后继值。

select nvl(min(missing_num),max(num)+1) first_missing_value
from (
select 
num,
case when num + 1 != lead(num) over (order by num)  then num + 1 end as  missing_num
from test_data
);

完整的表格不返回MISSING_NUM,因此原始查询返回NULL。使用NVL提供了预期的结果。

答案 1 :(得分:1)

找到差距的最佳方法是使用分析功能driver.get("http://xxxxxxxxxxxxxxxx") driver.implicitly_wait(10) driver.switch_to.frame(0) # frame located with index driver.find_element_by_id("ext1").send_keys("username") driver.find_element_by_id("ext2").send_keys("password") driver.find_element_by_xpath("//div[@class='btn_Login']/input").click() leadlag的示例:

lag

有关如何找到差距的更多信息here

答案 2 :(得分:1)

在Oracle 12.1及更高版本中,MATCH_RECOGNIZE可以快速解决此类问题:

<强>被修改即可。最初我选择了存在间隙的“下一个数字”(在示例中,值为9)。但这不是OP想要的,他想要第一个缺失的数字(在这种情况下为7)。我编辑了更改measures子句,找到了第一个丢失的号码。 结束修改

with test_data (num) as ( 
       select  4 from dual union all
       select  5 from dual union all
       select  6 from dual union all
       select  9 from dual union all
       select 10 from dual union all
       select 13 from dual
     )
-- end of test data; when you use the SQL query below,
-- replace test_data and num with your actual table and column names.
select result as num
from test_data
match_recognize (
  order by num
  measures last(b.num) + 1 as result
  pattern ( ^ a b* c )
  define b as num = prev(num) + 1,
         c as num > prev(num) + 1
)
;

NUM
---
  7