2012-02-17 4 views
0

Таблица1 выглядит следующим образом:найти недостающие значения в последовательности

Col1 
1 
2 
3 
4 
6 
7 
8 
9 
10 
13 
14 

Как показано выше col1 имеет последовательность значений, но по какой-то причине пользователь не вставить 5, 11 и так далее. Как узнать недостающие значения в последовательности. Здесь последовательность от 1 до 14, а отсутствующие значения - 5,11. Пожалуйста, помогите мне.

+1

Если вы отправляете код, образцы XML или данных, ** ПОЖАЛУЙСТА ** выделите эти строки в текстовом редакторе и нажмите кнопку «образцы кода» ('{}') на панели инструментов редактора, чтобы красиво отформатировать и выделить синтаксис Это! –

+0

Возможный дубликат [Запрос SQL для поиска Пропущенных порядковых номеров] (http://stackoverflow.com/questions/1057389/sql-query-to-find-missing-sequence-numbers) –

ответ

-1

Я бы сделал подзапрос в той же таблице, чтобы увидеть, существует ли другое число для текущего номера-1, и если его нет, вы знаете, что число было пропущено. Вы можете сделать +1 и этого.

выберите nt.numb, СЛУЧАЙ (SELECT COUNT (*) из таблицы, где онемение = nt.numb-1) = 0, то 'пропущен' ELSE 'не пропускается' из numbertable нт

+0

Не будет работать, если есть больше, чем один последовательный номер пропущен. –

+0

Очень хорошая точка, сделанная – Aklopper

3

Это будет работать для чисел 0 - 2000 для больших чисел, которые вам просто нужно перекрестно присоединить к исходному набору результатов.

with temp as (
    select distinct number 
from master..spt_Values 
where number between 0 and 2000 
) 

select * from 
temp t 
left join your_table y on y.col1 = t.number 
where y.col1 is null 

альтернативно с помощью перекрестного соединения

Это будет работать на миллиарды явно медленнее

WITH 
     L0 AS(SELECT 1 AS c UNION ALL SELECT 1), 
     L1 AS(SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B), 
     L2 AS(SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B), 
     L3 AS(SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B), 
     L4 AS(SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B), 
     L5 AS(SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B), 
     Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS n FROM L5) 

    select * from 
    l5 t 
    left join your_table y on y.col1 = t.n 
    where y.col1 is null 
0

Это, кажется, в значительной степени является дублирование

SQL query to find Missing sequence numbers

Там в предложения это будет работать:

SELECT  l.id + 1 as start 
FROM  Table1 as l 
LEFT JOIN Table1 as r on l.id + 1 = r.id 
WHERE  r.id IS NULL 

В противном случае вы можете присоединиться к своему столу с таблицей последовательностей. Из приведенного выше вопроса, вы можете посмотреть на http://www.projectdmx.com/tsql/tblnumbers.aspx, чтобы получить некоторые идеи о том, как создать соответствующую таблицу последовательности и присоединиться будет что-то вроде

SELECT  #sequence.value 
FROM  #sequence 
LEFT JOIN Table1 ON #sequence.value = Table1.value 
WHERE  Table1.value IS NULL 
0

Побочное примечание всем рекурсивных предложений КТР. Рекурсивный CTE увеличивает время, линейное по отношению к числу строк. Использование таблицы индикаторную или перекрестное соединение гораздо лучше использовать ...

Это будет работать:

-- data table 
CREATE TABLE #data (
    value INT 
) 

INSERT #data VALUES (1) 
INSERT #data VALUES (2) 
INSERT #data VALUES (3) 
INSERT #data VALUES (4) 
INSERT #data VALUES (6) 
INSERT #data VALUES (7) 
INSERT #data VALUES (8) 
INSERT #data VALUES (9) 
INSERT #data VALUES (10) 
INSERT #data VALUES (13) 
INSERT #data VALUES (14) 

-- normally i have a tally table already for stuff like this but I'll 
-- create one temporary here. 
CREATE TABLE #tmp_tally (
    n INT 
) 

DECLARE @n INT 
SET @n = 1 
WHILE @n < 14 
BEGIN 
    INSERT #tmp_tally VALUES (@n) 
    SET @n = @n + 1 
END 

SELECT 
    T.n, 
    CASE WHEN #data.value IS NULL THEN 'Missing' ELSE 'Not Missing' END 
FROM 
    #tmp_tally T 
    LEFT JOIN #data ON 
    T.n = #data.value 
WHERE 
    T.n <= (SELECT MAX(value) FROM #data) -- max of what you want to check against which is 14 in your example 

DROP TABLE #data 
DROP TABLE #tmp_tally 
+0

Просто назовите ее таблицей чисел. Это ничего не значит «подсчет»! :-) –

+0

Ничего плохого в подсчете ... это означает подсчет в таблице. Это также распространенное имя, поэтому значение фактически не имеет значения. – Asken

4

Как было сказано в других ответах, лучший выбор, чтобы сделать объединение с реальной последовательностью Таблица. Вы можете создать его, используя рекурсивное ОТВ:

DECLARE @MaxNumber INT 
SELECT @MaxNumber = MAX(Col1) FROM YourTable; 

WITH CTE AS 
(
    SELECT 1 Col1 
    UNION ALL 
    SELECT Col1+1 
    FROM CTE 
    WHERE Col1+1 <= @MaxNumber 
) 
SELECT A.Col1 
FROM CTE A 
LEFT JOIN YourTable B 
ON A.Col1 = B.Col1 
WHERE B.Col1 IS NULL 
OPTION(MAXRECURSION 0) 
0

Попробуйте это:

declare @min int 
declare @max int 

select @min = min(field_ID), @max = max(field_ID) from [Table] 

create table #tmp (Field_No int) 
while @min <= @max 
begin 
    if not exists (select * from [Table] where field_ID = @min) 
     insert into #tmp (seq_field) values (@min) 
    set @min = @min + 1 
end 
select * from #tmp 
drop table #tmp 

С вышеприведенным сценарием вы получите отсутствующее значение в столбце «ID» из #tmp таблицы.

Надеюсь, это поможет вам!

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