2009-04-07 97 views
3

我有ID的表格和定位如何在SQL中的組中按順序查找缺失值?

CREATE TABLE #MissingSequence (ID INT NOT NULL, Position INT NOT NULL) 
INSERT INTO #MissingSequence (ID,Position) 
SELECT 36,1 
UNION ALL SELECT 36,2 
UNION ALL SELECT 36,3 
UNION ALL SELECT 36,4 
UNION ALL SELECT 36,5 
UNION ALL SELECT 36,6 
UNION ALL SELECT 44,1 
UNION ALL SELECT 44,3 
UNION ALL SELECT 44,4 
UNION ALL SELECT 44,5 
UNION ALL SELECT 44,6 

我試圖找出是,如果有是ID位置序列在這種情況下,任何突破44.1和44.3之間

突破

我已經成功地一起解析:

SELECT l.ID 
    ,Start_Position = MIN(l.Position) + 1 
    ,Stop_Position = MIN(fr.Position) - 1 
FROM #MissingSequence l 
LEFT JOIN #MissingSequence r 
    ON l.Position = r.Position - 1 
LEFT JOIN #MissingSequence fr 
    ON l.Position < fr.Position 
WHERE r.Position IS NULL 
    AND fr.Position IS NOT NULL 
GROUP BY l.ID 

,但如果有多個ID值,這是行不通的。如果只有一個ID 44存在,它確實有效。

想法,意見,建議?

謝謝!

+0

你喜歡什麼輸出查看?有最大允許位置值嗎? – tpdi 2009-04-07 20:19:58

+0

沒有職位的最大數目...我正在處理的全表包含大約12k ID記錄,職位從3到x – 2009-04-07 20:30:38

+0

@Christopher,我的解決方案有什麼問題嗎? – 2009-04-07 20:34:47

回答

7

左自聯接是一個很好的本能,但我不認爲聚集體削減它,當然你需要在自連接中包含匹配-ID子句。

下面是使用(ANSI標準)版的空左加盟的想法,選擇頂行和底行和檢查兩者其實沒什麼:

SELECT 
    above.ID AS ID, below.Position+1 AS Start_Position, above.Position-1 AS End_Position 
FROM MissingSequence AS above 
JOIN MissingSequence AS below 
    ON below.ID=above.ID AND below.Position<above.Position-1 
LEFT JOIN MissingSequence AS inbetween 
    ON inbetween.ID=below.ID AND inbetween.Position BETWEEN below.Position+1 AND above.Position-1 
WHERE inbetween.ID IS NULL; 

+----+----------------+--------------+ 
| ID | Start_Position | End_Position | 
+----+----------------+--------------+ 
| 44 |    2 |   2 | 
+----+----------------+--------------+ 
2

這個查詢找到了簡單的單詞,希望有用;如果你是在SQL 2005,您可以使用一個CTE

SELECT ID, Position + 1 
FROM #MissingSequence t1 
WHERE (Position + 1) NOT IN (SELECT Position FROM #MissingSequence t2 WHERE t1.ID = t2.ID) 
AND Position <> (SELECT MAX(Position) FROM #MissingSequence t2 WHERE t1.ID = t2.ID) 
0
create database testing 
use testing; 
create table sequence (
    id int not null primary key 
); 

insert into sequence(id) values 
    (1), (2), (3), (4), (6), (7), (8), (9), 
    (10), (15), (16), (17), (18), (19), (20); 

select * from sequence 

Create PROCEDURE test_proce(@mode varchar(50)) 
AS 
BEGIN 
    declare @se int; 
    set @se=0; 
    set @se=(
     select top 1 t.id + 1 
     from sequence t 
     left join sequence x on x.id = t.id + 1 
     where x.id is null 
     order by t.id 
    ); 
    select * from sequence where id<@se; 
END 

exec test_proce 'mode'