インタビューで次のような質問を受けました: 自然数のテーブルに欠けているものがある場合、最初のテーブルの数のギャップの始まりと 2 番目のテーブルで終わる 2 つのテーブルの出力を提供してください。例:
____ ________ | | | | | | | | | | | | 1 | | | 3 | 3 | | | 2 | | | 6 | 7 | | | 4 | | | 10| 12| | | 5 | |___|___| | | 8 | | | 9 | | | 13 | |____|
インタビューで次のような質問を受けました: 自然数のテーブルに欠けているものがある場合、最初のテーブルの数のギャップの始まりと 2 番目のテーブルで終わる 2 つのテーブルの出力を提供してください。例:
____ ________ | | | | | | | | | | | | 1 | | | 3 | 3 | | | 2 | | | 6 | 7 | | | 4 | | | 10| 12| | | 5 | |___|___| | | 8 | | | 9 | | | 13 | |____|
これは Phil Sandler の回答とほとんど同じですが、これは 2 つの別個のテーブルを返すはずです (そして、よりきれいに見えると思います) (少なくとも SQL Server では機能します)。
DECLARE @temp TABLE (num int) @temp 値に挿入 (1)、(2)、(4)、(5)、(8)、(9)、(13) DECLARE @min INT、@max INT SELECT @min = MIN(数値)、@max = MAX(数値) 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
これは 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
これはDB固有のSQLなしで機能し、おそらく少しきれいにすることができますが、機能します
編集: StackExchange Data Explorer の このクエリでこれが機能していることを確認できます。
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
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)
このようなもの:
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
「rownum」構文は、DBMS によって異なります。上記は SQL Server で機能する可能性がありますが、テストしていません。
コメントの 1 つが指摘したように、多くの DBMS には、これを容易にする分析機能があります。