[英]SQL to find missing numbers in sequence starting from min?
我找到了几个SQL查询的例子,它们会在序列中找到缺失的数字。 例如这一个:
Select T1.val+1
from table T1
where not exists(select val from table T2 where T2.val = T1.val + 1);
这只会在现有序列中找到空白。 我想从最小值开始找到序列中的间隙。
例如,如果我的序列中的值是2,4,那么上面的查询将返回3,5。
我想指定我的序列必须从0开始,所以我希望查询返回0,1,3,5。
如何在查询中添加最小值?
这在Postgres非常简单:
select x.i as missing_sequence_value
from (
select i
from generate_series(0,5) i -- 0,5 are the lower and upper bounds you want
) x
left join the_table t on t.val = x.i
where t.val is null;
SQLFiddle: http ://www.sqlfiddle.com/#!15 / acb07 / 1
编辑
Oracle解决方案有点复杂,因为生成数字需要一种解决方法
with numbers as (
select level - 1 as val
from dual
connect by level <= (select max(val) + 2 from the_table) -- this is the maximum
), number_range as (
select val
from numbers
where val >= 0 -- this is the minimum
)
select nr.val as missing_sequence_value
from number_range nr
left join the_table t on t.val = nr.val
where t.val is null;
SQLFiddle: http ://www.sqlfiddle.com/#!4/71584/4
这个想法(在两种情况下)都是生成一个您感兴趣的数字列表(从0到5),然后对表中的值进行外连接。 外连接不从表中返回某些内容的行(这是where t.val is null
的条件)是缺少的值。
Oracle解决方案需要两个公用表表达式(“CTE”,“with”事物),因为您无法在生成数字的第一个CTE中添加where level >= x
。
请注意, connect by level <= ...
依赖于使用connect by
的未记录(且不受支持)的方式。 但是有这么多人使用它来获得一个“数字生成器”,我怀疑Oracle实际上会删除它。
如果必须选择使用公用表表达式 ,则可以生成一系列数字并将其用作数字源。
变量@start
和@end
定义了数字的范围(您可以轻松地使用来自yourtable的max(val)作为结束)。
此示例适用于MS SQL Server(但CTE是许多数据库支持的SQL 99功能):
declare @start int, @end int
select @start=0, @end=5
;With sequence(num) as
(
select @start as num
union all
select num + 1
from sequence
where num < @end
)
select * from sequence seq
where not exists(select val from YourTable where YourTable.val = seq.num)
Option (MaxRecursion 1000)
只是为上面的建议提出了2个小变化,两者都是针对Oracle的。
首先是jpw
使用递归公用表表达式(CTE)呈现的小变化; 只是为了证明这种技术在Oracle中也可用。
WITH
seq (val)
AS (
SELECT 0 FROM dual
UNION ALL
SELECT val + 1
FROM seq
WHERE val < (
SELECT MAX(val) FROM the_table -- note below
)
)
SELECT
seq.val AS missing_sequence_value
FROM seq
LEFT JOIN the_table t
ON seq.val = t.val
WHERE t.val IS NULL
ORDER BY
missing_sequence_value
;
与SQL Server的显着区别:您可以使用子查询来限制递归
此外,Oracle文档通常引用子查询因子,例如subquery_factoring_clause::=
而不是CTE
第二个是a_horse_with_no_name
使用的按级别连接的使用的a_horse_with_no_name
Level是Oracle的分层查询中可用的伪列, 层次结构的根是1.当按级别使用connect时,默认情况下这将从1开始
对于这种变化,我只是希望证明它根本不需要与CTE结合,因此语法可以非常简洁。
SELECT
seq.val AS missing_sequence_value
FROM (
SELECT
level - 1 AS val
FROM dual
CONNECT BY LEVEL <= (SELECT max(val) FROM the_table)
) seq
LEFT JOIN the_table t
ON seq.val = t.val
WHERE t.val IS NULL
ORDER BY
missing_sequence_value
;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.