How to find the missing value in a sequence within groups in SQL?

I have a table of identifiers and positions

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

What I'm trying to find is that there is any gap in the sequence of positions by identifier in this case, the gap between 44.1 and 44.3

I managed to parse together:

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

but it does not work if there are multiple ID values. It works if there is only one ID, 44.

thoughts, comments, suggestions?

thanks!

+3
source share
3 answers

Left-handed self-connection was a good instinct, but I don’t think aggregates are going to cut it off, and of course you will need to include the match-ID clause in your self-connections.

(, ANSI), null-left-join, :

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 | 
+----+----------------+--------------+
+7

, ; 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)
+2
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'
0
source

Source: https://habr.com/ru/post/1706072/


All Articles