Как выбрать строки, которые имеют непрерывное значение для столбца

#sql #sql-server #sql-server-2005

#sql #sql-сервер #sql-server-2005

Вопрос:

У меня есть таблица, подобная приведенной ниже

 CREATE TABLE [dbo].[LINE](
[ID] [nvarchar](50) NOT NULL,
[LINE_NUM] [int] NOT NULL
) ON [PRIMARY]

insert into LINE select '01201301090100600004', '1'
insert into LINE select '01201301090100600004', '2'
insert into LINE select '01201301090100600004', '3'
insert into LINE select '01201301090100600004', '4'
insert into LINE select '01201301090100600005', '1'
insert into LINE select '01201301090100600005', '4'
insert into LINE select '01201301090100600005', '5'
insert into LINE select '01201301100045200002', '1'
insert into LINE select '01201301100045200002', '2'
insert into LINE select '01201301100045200002', '3'
insert into LINE select '01201301100081300008', '1'
insert into LINE select '01201301100081300008', '3'
 

я хочу выбрать записи, в которых столбец LINE_NUM является непрерывным. Оно должно начинаться с 1. Поэтому я хочу выбрать только следующее

    '01201301090100600004', '1'
   '01201301090100600004', '2'
   '01201301090100600004', '3'
   '01201301090100600004', '4'
   '01201301100045200002', '1'
   '01201301100045200002', '2'
   '01201301100045200002', '3'
 

Как мне это сделать?

Отредактированный вопрос:

Я ищу, чтобы получить различные идентификаторы, где число СТРОК начинается с 1, а также, если для идентификатора имеется более одного числа СТРОК, затем проверьте, являются ли они последовательными, и извлеките эти идентификаторы?

я использовал это, чтобы получить его

 SELECT id,
   m.line_num,
   m.new_line_num
FROM   (SELECT t.line_num AS old_line_num,
           t.*
    FROM   (SELECT t.*,
                   Row_number()
                     OVER (
                       partition BY clm_id
                       ORDER BY line_num ) AS new_line_num
            FROM   line t) t) m
WHERE  m.line_num <> m.new_line_num  
 

Комментарии:

1. @Neeku ВЫБЕРИТЕ ID , m.LINE_NUM ,m.new_line_num ИЗ (ВЫБЕРИТЕ t.LINE_NUM КАК old_line_num , т.* ИЗ (ВЫБЕРИТЕ t.* , row_number() ПОВЕРХ (РАЗДЕЛЕНИЕ ПО ПОРЯДКУ CLM_ID ПО LINE_NUM) КАК new_line_num ИЗ СТРОКИ t ) t ) m ГДЕ m.LINE_NUM <> m .new_line_num

Ответ №1:

Вы можете сделать это с row_number() помощью . Если значения являются последовательными (более точный термин, чем «непрерывный»), то разница будет постоянной:

 select id, line_num
from (select t.*,
             min(diff) over (partition by id) as mindiff,
             max(diff) over (partition by id) as maxdiff
      from (select t.*,
                   (line_num - row_number() over (partition by id order by line_num)) as diff
            from table t
           ) t
     ) t
where mindiff = maxdiff and mindiff = 1;
 

Если вы просто хотите найти id s, в которых нет пробелов, вам даже не нужны оконные функции:

 select t.id
from table t
group by t.id
having (max(line_num) - min(line_num)   1 = count(distinct line_num));
 

Комментарии:

1. Я все еще получаю идентификаторы с номерами разорванных строк

2. @user176047 . , , Вы можете отредактировать свой вопрос и привести несколько примеров? Или, что еще лучше, настройте SQL-скрипку?

3. @user176047 . , , Запрос в вашем пересмотренном вопросе не является запросом в моем ответе.

Ответ №2:

Вы могли бы использовать ROW_NUMBER() OVER (ORDER BY ID) для упорядочения по столбцу ID. Затем используйте это, чтобы проверить, имеет ли следующая строка Line_Num 1 :

 WITH CTE AS
(
    SELECT IdNum = ROW_NUMBER() OVER (ORDER BY ID), *
    FROM dbo.LINE
)
SELECT ID,LINE_NUM 
FROM CTE
WHERE (SELECT LINE_NUM FROM CTE c2
       WHERE c2.IdNum = CTE.IdNum   1) = LINE_NUM   1
 

Demo

Комментарии:

1. для запуска требуется много времени, но все равно выбираются идентификаторы с непоследовательным LINE_NUM

Ответ №3:

Может быть, мы также можем сделать это

 declare @Line  TABLE (
    [ID] [nvarchar](50) NOT NULL,
    [Line_NUM] [int] NOT NULL
    ) 

    insert into @Line select '01201301090100600004', '1'
    insert into @Line select '01201301090100600004', '2'
    insert into @Line select '01201301090100600004', '3'
    insert into @Line select '01201301090100600004', '4'
    insert into @Line select '01201301090100600005', '1'
    insert into @Line select '01201301090100600005', '4'
    insert into @Line select '01201301090100600005', '5'
    insert into @Line select '01201301100045200002', '1'
    insert into @Line select '01201301100045200002', '2'
    insert into @Line select '01201301100045200002', '3'
    insert into @Line select '01201301100081300008', '1'
    insert into @Line select '01201301100081300008', '3'
    ;WITH CTE AS 
    (
    select ID,Line_NUM,RN=ROW_NUMBER()OVER(PARTITION by ID ORDER BY Line_NUM ) from @Line
    ),CTE2 AS
    (
    Select distinct 
    ID,Line_NUM,RR = ROW_NUMBER()OVER(PARTITION by ID ORDER BY  Line_NUM )
    from CTE 
    WHERE Line_NUM = RN 
    GROUP BY ID,Line_NUM,RN 
    )
    ,CTE3 AS
    (
    Select C.id,C.Line_NUM,RANK() OVER(Order By c.id) as t_index FROM CTE2 C
    GROUP BY C.ID,C.RR,c.Line_NUM
    )

    Select ID,Line_Num from 
    (Select DISTINCT cc.ID,CC.Line_NUM,COUNT(CC.t_index)OVER (Partition by cc.ID)RS from CTE3  CC)Z
      WHERE RS > 1