Domanda

Ho una tabella di ID e posizioni

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

Quello che sto cercando di trovare è se c'è qualche interruzione nella sequenza di posizioni di ID in questo caso la rottura tra 44,1 e 44,3

Sono riuscito a analizzare insieme:

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

ma non funziona se ci sono più valori ID. Esso funziona anche se solo un singolo ID, 44 esiste.

pensieri, commenti, suggerimenti?

grazie!

È stato utile?

Soluzione

La sinistra self-join è stato un buon istinto, ma non credo che gli aggregati stanno andando a tagliare, e sicuramente avresti bisogno di includere la clausola corrispondente-ID nella vostra auto-join.

Ecco una versione (ANSI-compliant) utilizzando il null-sinistra-join idea, selezionando una riga superiore e una fila inferiore e di controllo non c'è nulla tra di loro:

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

Altri suggerimenti

Questa query ha visto gli slittamenti, la speranza di essere utile; se siete in SQL 2005, è possibile utilizzare un 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)
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'
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top