我有一个带有 int 值列的表,它的值在 0 到 43 之间(都包括在内)。
我想要一个返回不在表中的范围 [0,44) 的最小值的查询。
例如:
如果表包含:3,5,14。如果表包含:0,1,14,则查询应返回 0。
如果表包含:0,3,14,则查询应返回 2。
查询应返回1
如果表包含所有值,则查询应返回空。
我怎样才能做到这一点?
由于您想要的值是0
或大于表中存在的值,因此您可以这样做;
SELECT MIN(value)
FROM (SELECT 0 value UNION SELECT value+1 FROM MyTable) a
WHERE value < 44 AND value NOT IN (SELECT value FROM MyTable)
一种方法是创建另一个包含整数的表,[0,43]
然后左连接并查找 NULL,NULL 会告诉您缺少哪些值。
假设你有:
create table numbers (n int not null);
此表包含从 0 到 43(含)的整数。如果您的表是t
并且有一个n
包含感兴趣数字的列,那么:
select n.n
from numbers n left join t on n.n = t.n
where t.n is null
order by n.n
limit 1
应该给你你想要的结果。
当您使用序列时,这是一种相当常见的 SQL 技术。最常见的用途可能是日历表。
有点 hacky 和 MySQL 特定的:
SELECT NULLIF(MAX(IF(val=@min, @min:=(val+1), @min)), @max) as min_empty
FROM (
SELECT DISTINCT val
FROM table1
-- WHERE val BETWEEN 0 AND 43
ORDER BY val) as vals, (SELECT @min:=0, @max:=44) as init;
一种方法是生成一组具有整数值的 44 行,然后针对表中的不同值集执行反连接,并获取最小值。
SELECT MIN(r.val) AS min_val
FROM ( SELECT 0 AS val UNION ALL
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
-- ...
SELECT 44
) r
LEFT
JOIN ( SELECT t.int_valued_col
FROM mytable t
WHERE t.int_valued_col >= 0
AND t.int_valued_col <= 43
GROUP BY t.int_valued_col
) v
ON v.int_valued_col = r.col
WHERE v.int_valued_col IS NULL