Tou*_*uko 97 sql gaps-and-islands
我想在SQL表的计数器列中找到第一个"间隙".例如,如果有值1,2,4和5,我想找出3.
我当然可以按顺序获取值并手动完成它,但我想知道是否有办法在SQL中执行它.
此外,它应该是非常标准的SQL,使用不同的DBMS.
Qua*_*noi 168
在MySQL和PostgreSQL:
SELECT id + 1
FROM mytable mo
WHERE NOT EXISTS
(
SELECT NULL
FROM mytable mi
WHERE mi.id = mo.id + 1
)
ORDER BY
id
LIMIT 1
Run Code Online (Sandbox Code Playgroud)
在SQL Server:
SELECT TOP 1
id + 1
FROM mytable mo
WHERE NOT EXISTS
(
SELECT NULL
FROM mytable mi
WHERE mi.id = mo.id + 1
)
ORDER BY
id
Run Code Online (Sandbox Code Playgroud)
在Oracle:
SELECT *
FROM (
SELECT id + 1 AS gap
FROM mytable mo
WHERE NOT EXISTS
(
SELECT NULL
FROM mytable mi
WHERE mi.id = mo.id + 1
)
ORDER BY
id
)
WHERE rownum = 1
Run Code Online (Sandbox Code Playgroud)
ANSI (无处不在,效率最低):
SELECT MIN(id) + 1
FROM mytable mo
WHERE NOT EXISTS
(
SELECT NULL
FROM mytable mi
WHERE mi.id = mo.id + 1
)
Run Code Online (Sandbox Code Playgroud)
支持滑动窗口功能的系统:
SELECT -- TOP 1
-- Uncomment above for SQL Server 2012+
previd
FROM (
SELECT id,
LAG(id) OVER (ORDER BY id) previd
FROM mytable
) q
WHERE previd <> id - 1
ORDER BY
id
-- LIMIT 1
-- Uncomment above for PostgreSQL
Run Code Online (Sandbox Code Playgroud)
小智 12
如果您的第一个值为id = 1,那么您的答案都可以正常工作,否则将无法检测到此差距.例如,如果您的表ID值为3,4,5,则查询将返回6.
我做了这样的事
SELECT MIN(ID+1) FROM (
SELECT 0 AS ID UNION ALL
SELECT
MIN(ID + 1)
FROM
TableX) AS T1
WHERE
ID+1 NOT IN (SELECT ID FROM TableX)
Run Code Online (Sandbox Code Playgroud)
第一件事就是我的想法.不确定这样做是否一个好主意,但应该有效.假设表是t,并且列是c:
SELECT t1.c+1 AS gap FROM t as t1 LEFT OUTER JOIN t as t2 ON (t1.c+1=t2.c) WHERE t2.c IS NULL ORDER BY gap ASC LIMIT 1
编辑:这个可能更快(更短!):
SELECT min(t1.c)+1 AS gap FROM t as t1 LEFT OUTER JOIN t as t2 ON (t1.c+1=t2.c) WHERE t2.c IS NULL
确实没有非常标准的SQL方法可以执行此操作,但是通过某种形式的限制子句,您可以执行此操作
SELECT `table`.`num` + 1
FROM `table`
LEFT JOIN `table` AS `alt`
ON `alt`.`num` = `table`.`num` + 1
WHERE `alt`.`num` IS NULL
LIMIT 1
Run Code Online (Sandbox Code Playgroud)
(MySQL,PostgreSQL)
要么
SELECT TOP 1 `num` + 1
FROM `table`
LEFT JOIN `table` AS `alt`
ON `alt`.`num` = `table`.`num` + 1
WHERE `alt`.`num` IS NULL
Run Code Online (Sandbox Code Playgroud)
(SQL Server)
要么
SELECT `num` + 1
FROM `table`
LEFT JOIN `table` AS `alt`
ON `alt`.`num` = `table`.`num` + 1
WHERE `alt`.`num` IS NULL
AND ROWNUM = 1
Run Code Online (Sandbox Code Playgroud)
(甲骨文)
这适用于SQL Server - 无法在其他系统中测试它,但它似乎是标准的......
SELECT MIN(t1.ID)+1 FROM mytable t1 WHERE NOT EXISTS (SELECT ID FROM mytable WHERE ID = (t1.ID + 1))
Run Code Online (Sandbox Code Playgroud)
你也可以在where子句中添加一个起点......
SELECT MIN(t1.ID)+1 FROM mytable t1 WHERE NOT EXISTS (SELECT ID FROM mytable WHERE ID = (t1.ID + 1)) AND ID > 2000
Run Code Online (Sandbox Code Playgroud)
因此,如果您有2000年,2001年,2002年和2005年,2003年和2004年不存在,它将返回2003年.