2009-04-07 12 views
3

я есть таблица идентификаторов и позицииКак найти отсутствующее значение в последовательности внутри групп в 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

+0

Максимальное количество позиций ... полная таблица, над которой я работаю, содержит около 12 тыс. Идентификационных записей, позиции от 3 до x –

+0

@ Кристофер, что-то не так с моим решением? –

ответ

7

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

Вот (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 | 
+----+----------------+--------------+ 
+0

Я думаю, что это как раз ... HAVING раздражает, но это лучше, чем я придумал, спасибо +1 [x] –

+0

Oh! Конечно, вы можете сделать это без ИГРЫ. Обновленный запрос выше; должен также немного улучшиться. – bobince

+0

удивительный, это прибило его! –

2

Этот запрос содержит подсказки, надеющиеся быть полезными; если вы в SQL Server 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

Не будет ли это обнаруживать только одно отсутствующие значения позиции, а не их выполнение? – bobince

+0

ah ok, fine, sure –

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' 

 Смежные вопросы

  • Нет связанных вопросов^_^