SQL用于选择具有相同值的连续记录

Tax*_*Max 5 sql gaps-and-islands sql-server-2014

我有一张测量表.每分钟进行一次测量.我需要为同一个device_id连续多次选择具有相同sample_value的行.

这是初始数据:

    sample_date sample_time device_id   sample_value
    20180701    1010        111         11
    20180701    1011        111         12
    20180701    1012        111         13
    20180701    1013        222         11
    20180701    1014        222         11
    20180701    1015        222         12
    20180701    1016        111         12
    20180701    1017        111         11
    20180701    1018        222         13
    20180701    1019        222         12
    20180701    1020        222         13
    20180701    1021        222         12
    20180701    1022        222         12
    20180701    1023        111         12
    20180701    1024        111         13
    20180701    1025        111         13
    20180701    1026        111         12
    20180701    1027        111         13
    20180701    1028        222         14
    20180701    1029        222         13
    20180701    1030        222         14
    20180701    1031        222         14
    20180701    1032        222         14
    20180701    1033        222         14
    20180701    1034        222         14
    20180701    1035        222         14
    20180701    1036        111         13
    20180701    1037        111         13
    20180701    1038        111         14
    20180701    1039        111         13
Run Code Online (Sandbox Code Playgroud)

这是我正在寻找的结果:

sample_date sample_time device_id   sample_value
20180701    1013        222         11
20180701    1014        222         11
20180701    1021        222         12
20180701    1022        222         12
20180701    1024        111         13
20180701    1025        111         13
20180701    1030        222         14
20180701    1031        222         14
20180701    1032        222         14
20180701    1033        222         14
20180701    1034        222         14
20180701    1035        222         14
20180701    1036        111         13
20180701    1037        111         13
Run Code Online (Sandbox Code Playgroud)

这是测试数据:

IF OBJECT_ID('samples', 'U') IS NOT NULL 
DROP TABLE samples; 

create table samples (
sample_date int,
sample_time int,
device_id int,
sample_value int
)

insert samples
values
(20180701, 1010, 111, 11)
,(20180701, 1011, 111, 12)
,(20180701, 1012, 111, 13)
,(20180701, 1013, 222, 11)
,(20180701, 1014, 222, 11)
,(20180701, 1015, 222, 12)
,(20180701, 1016, 111, 12)
,(20180701, 1017, 111, 11)
,(20180701, 1018, 222, 13)
,(20180701, 1019, 222, 12)
,(20180701, 1020, 222, 13)
,(20180701, 1021, 222, 12)
,(20180701, 1022, 222, 12)
,(20180701, 1023, 111, 12)
,(20180701, 1024, 111, 13)
,(20180701, 1025, 111, 13)
,(20180701, 1026, 111, 12)
,(20180701, 1027, 111, 13)
,(20180701, 1028, 222, 14)
,(20180701, 1029, 222, 13)
,(20180701, 1030, 222, 14)
,(20180701, 1031, 222, 14)
,(20180701, 1032, 222, 14)
,(20180701, 1033, 222, 14)
,(20180701, 1034, 222, 14)
,(20180701, 1035, 222, 14)
,(20180701, 1036, 111, 13)
,(20180701, 1037, 111, 13)
,(20180701, 1038, 111, 14)
,(20180701, 1039, 111, 13)

select * from samples
Run Code Online (Sandbox Code Playgroud)

这是我正在尝试使用的SQL,但我不知道如何设置正确的分区.

    select *
    from (select    sample_date,
                    sample_time,
                    device_id,
                    sample_value,
                    row_number() over (partition by sample_date,
                                                    device_id,
                                                    sample_value
                                            order by sample_date,
                                                    sample_time,
                                                    device_id) as occurrence
    from samples) t
    where     occurrence > 1
Run Code Online (Sandbox Code Playgroud)

类似主题:

选择语句以查找某些字段的重复项

如何根据列的值查找连续的行?

Gor*_*off 0

我想你想使用lag()/ lead()

select s.*
from (select s.*,
             lag(device_id) over (order by sample_date, sample_time) as prev_di,
             lead(device_id) over (order by sample_date, sample_time) as next_di,
             lag(sample_value) over (order by sample_date, sample_time) as prev_sv,
             lead(sample_value) over (order by sample_date, sample_time) as next_sv
      from samples s
     ) s
where (prev_sv = sample_value and prev_di = device_id) or
      (next_sv = sample_value and prev_di = device_id);
Run Code Online (Sandbox Code Playgroud)

是一个 SQL Fiddle。

如果您特别希望相邻行成为下一个时间单位,您可以使用exists

select s.*
from samples s
where exists (select 1
              from samples s2 
              where s2.sample_date = s.sample_date and
                    s2.sample_time in (s.sample_time - 1, s.sample_time + 1
             );
Run Code Online (Sandbox Code Playgroud)