我在接受采访时得到以下问题: 给定一个具有一些缺失的自然数的表,提供两个表的输出,在第一个表中的数字间隙的开始 并以秒结束。 例如:
____ ________ | | | | | | 1 | | 3 | 3 | | 2 | | 6 | 7 | | 4 | | 10| 12| | 5 | |___|___| | 8 | | 9 | | 13 | |____|
答案 0 :(得分:6)
虽然这与Phil Sandler的答案几乎相同,但这应该返回两个单独的表(我觉得它看起来更干净)(至少在SQL Server中有效):
DECLARE @temp TABLE (num int) INSERT INTO @temp VALUES (1),(2),(4),(5),(8),(9),(13) DECLARE @min INT, @max INT SELECT @min = MIN(num), @max = MAX(num) FROM @temp SELECT t.num + 1 AS range_start FROM @temp t LEFT JOIN @temp t2 ON t.num + 1 = t2.num WHERE t.num < @max AND t2.num IS NULL SELECT t.num - 1 AS range_end FROM @temp t LEFT JOIN @temp t2 ON t.num - 1 = t2.num WHERE t.num > @min AND t2.num IS NULL
答案 1 :(得分:2)
Itzik Ben Gan写了很多关于这些“差距和岛屿”问题的文章。他的row_number
解决方案是
WITH C AS
(
SELECT N, ROW_NUMBER() OVER (ORDER BY N) AS RN
FROM t
)
SELECT Cur.N+1,Nxt.N-1
FROM C AS Cur
JOIN C AS Nxt ON Nxt.RN = Cur.RN+1
WHERE Nxt.N-Cur.N>1
来自同一来源的没有row_number
的解决方案。
SELECT N+1 AS start_range,
(SELECT MIN(B.N) FROM t AS B WHERE B.N > A.N)-1 AS end_range
FROM t AS A
WHERE NOT EXISTS(SELECT * FROM t AS B WHERE B.N = A.N+1)
AND N< (SELECT MAX(N) FROM t)
答案 2 :(得分:2)
这可以在没有DB特定SQL的情况下工作,它可能会变得更干净但它确实有效
修改强>
您可以在StackExchange Data Explorer 3>上看到这个Query
SELECT low,high FROM
(
SELECT col1, low
FROM
(Select n1.col1 col1, min(n2.col1) + 1 low
from numbers n1
inner join numbers n2
on n1.col1 < n2.col1
Group by n1.col1) t
WHERE t.low not in (SELECT col1 FROM NUMBERS)
and t.low < (Select MAX(col1) from numbers)
) t
INNER JOIN
(
SELECT col1 - 1 col1, high
FROM
(Select n1.col1 col1 , min(n2.col1) - 1 high
from numbers n1
inner join numbers n2
on n1.col1 < n2.col1
Group by n1.col1) t
WHERE t.high not in (SELECT col1 FROM NUMBERS)
) t2
ON t.col1 = t2.col1
答案 3 :(得分:1)
这样的事情:
SELECT col1, col2 FROM
(
SELECT x + 1 as col1,
ROW_NUMBER() OVER(ORDER BY x) AS 'rownum'
FROM tbl y
WHERE NOT EXISTS (SELECT x FROM tbl z WHERE z.x = y.x + 1)
AND x <> (SELECT MAX(x) FROM tbl)
) a
INNER JOIN
(
SELECT x - 1 as col2,
ROW_NUMBER() OVER(ORDER BY x) AS 'rownum'
FROM tbl y
WHERE NOT EXISTS (SELECT x FROM tbl z WHERE z.x = y.x - 1)
AND x <> (SELECT MIN(x) FROM tbl)
) b
ON a.rownum = b.rownum
对于不同的DBMS,“rownum”语法将有所不同。以上内容可能适用于SQL Server,但我还没有测试过它。
正如其中一条评论所指出的那样,许多DBMS都有分析功能,可以让这更容易。
答案 4 :(得分:1)
这是SQL Server语法:
CREATE TABLE #temp (columnA int)
INSERT INTO #temp VALUES(1)
INSERT INTO #temp VALUES(2)
INSERT INTO #temp VALUES(4)
INSERT INTO #temp VALUES(5)
INSERT INTO #temp VALUES(8)
INSERT INTO #temp VALUES(9)
INSERT INTO #temp VALUES(13)
SELECT
t1.columnA - 1
FROM
#temp t1
LEFT JOIN #temp t2 ON t1.columnA = t2.ColumnA + 1
WHERE
t2.ColumnA IS NULL
AND t1.ColumnA != (SELECT MIN(ColumnA) from #temp)
SELECT
t1.columnA + 1
FROM
#temp t1
LEFT JOIN #temp t2 ON t1.columnA = t2.ColumnA - 1
WHERE
t2.ColumnA IS NULL
AND t1.ColumnA != (SELECT MAX(ColumnA) from #temp)
DROP table #temp
答案 5 :(得分:0)
您可以使用Lag
功能访问上一行:
create table #a (n int)
insert #a values(1)
insert #a values(2)
insert #a values(4)
insert #a values(5)
insert #a values(8)
insert #a values(9)
insert #a values(13)
select prev + 1, n - 1 from
(select lag(n) over(order by n) as prev, n
from #a) a
where prev < n - 1
结果:
|3 |3 |
|6 |7 |
|10 |12 |
答案 6 :(得分:0)
1。第1步
从ID列表中获取当前ID和所有可用的下一个ID
select l1.id curr_id,l2.id next_id from
id_list l1,id_List l2
where l1.id < l2.id;
2。步骤2
从上面的列表中,我们将看到所有组合,但每个当前ID仅过滤一个组合,其下一个ID最小,为此,获取每个当前ID的最小当前ID和最小下一个ID。按当前ID使用分组方式
with id_combinations as
(
select l1.id curr_id,l2.id next_id from
id_list l1,id_List l2
where l1.id < l2.id
)
select min(curr_id)+1 missing_id_start -- Need to add 1 from current available id
,min(next_id)-1 missing_id_end -- Need to subtract 1 from next available id
from id_combinations
group by curr_id
having min(curr_id)+1 < min(next_id) -- Filter to get only the missing ranges