Как найти пропущенное значение в последовательности в группах в SQL? - PullRequest
3 голосов
/ 08 апреля 2009

у меня есть таблица идентификаторов и позиций

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. Это работает, если существует только один идентификатор, 44.

мысли, комментарии, предложения?

спасибо!

Ответы [ 3 ]

8 голосов
/ 08 апреля 2009

Левое самостоятельное объединение было хорошим инстинктом, но я не думаю, что агрегаты будут его сокращать, и, конечно, вам нужно будет включить в свой самообъединение предложение match-ID.

Вот (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 | 
+----+----------------+--------------+
2 голосов
/ 08 апреля 2009

Этот запрос определяет ошибки, надеюсь, будет полезен; если вы в 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 голосов
/ 20 февраля 2014
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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...