我找到了几个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。
如何在查询中添加最小值?
答案 0 :(得分: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解决方案需要两个常用的表表达式(&#34; CTE&#34;,&#34;有&#34;事物),因为您无法在第一个CTE中添加where level >= x
产生数字。
请注意,connect by level <= ...
依赖于使用connect by
的未记录(且不受支持)的方式。但是有这么多人正在使用它来获得一个数字生成器&#34;我怀疑Oracle实际上会删除它。
答案 1 :(得分:2)
如果您必须选择使用common table expression,您可以生成一系列数字并将其用作数字来源。
变量@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 :(得分:2)
仅针对上述建议提出两个小变体,两者都适用于Oracle。
首先是jpw
使用recursive公用表格表达式(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
Level是Oracle hierarchical queries中可用的伪列,层次结构的根是1.当按层次使用连接时,默认情况下这将从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
;