在SQL Server中检索指定行上方和下方的行

时间:2014-04-03 11:33:42

标签: sql sql-server

我在SQL Server中有一个包含超过一百万行数据和30多列(字段)的大型数据库。我已经运行了一个程序,从一张表中找到了我特别感兴趣的97条特定行。我没有包括我用来隔离这97行的各种逻辑步骤。

我现在需要做的是按日期和时间对表格进行排序,并且不仅检索我已识别的97行(我有他们的ID),还检索每个上面和下面的5个数据行。排序表中的97。

有谁知道如何实现这一目标?

SELECT *
FROM table
WHERE ID IN (. . list of 97 IDs . . )
ORDER BY Date, Time
/* and get the 5 rows above and below each of the 97 specified lines */

我考虑过使用指定ID和ID其他行之间的差异,但是Date,Time排序意味着ID无论如何都不是有序的,因此该字段不能用于实现我的目标。

2 个答案:

答案 0 :(得分:1)

使用LAG和LEAD获取之前和之后的记录及其ID:

with wanted_ids as (select list of 97 IDs)
select *
from
(
  select
    thetable.*,
    lag(id,1) over (order by thedate, thetime) as lag1,
    lag(id,2) over (order by thedate, thetime) as lag2,
    lag(id,3) over (order by thedate, thetime) as lag3,
    lag(id,4) over (order by thedate, thetime) as lag4,
    lag(id,5) over (order by thedate, thetime) as lag5,
    lead(id,1) over (order by thedate, thetime) as lead1,
    lead(id,2) over (order by thedate, thetime) as lead2,
    lead(id,3) over (order by thedate, thetime) as lead3,
    lead(id,4) over (order by thedate, thetime) as lead4,
    lead(id,5) over (order by thedate, thetime) as lead5
  from thetable
)
where id in wanted_ids
or lag1 in wanted_ids
or lag2 in wanted_ids
or lag3 in wanted_ids
or lag4 in wanted_ids
or lag5 in wanted_ids
or lead1 in wanted_ids
or lead2 in wanted_ids
or lead3 in wanted_ids
or lead4 in wanted_ids
or lead5 in wanted_ids
order by thedate, thetime;

您可以对联接执行相同的操作。只知道两次没有记录(当范围重叠时)。使用distict来避免这种情况。

select distinct all_records.*
from
(
  select
    thetable.*,
    lag(id,1) over (order by thedate, thetime) as lag1,
    lag(id,2) over (order by thedate, thetime) as lag2,
    lag(id,3) over (order by thedate, thetime) as lag3,
    lag(id,4) over (order by thedate, thetime) as lag4,
    lag(id,5) over (order by thedate, thetime) as lag5,
    lead(id,1) over (order by thedate, thetime) as lead1,
    lead(id,2) over (order by thedate, thetime) as lead2,
    lead(id,3) over (order by thedate, thetime) as lead3,
    lead(id,4) over (order by thedate, thetime) as lead4,
    lead(id,5) over (order by thedate, thetime) as lead5
  from thetable
) all_records
inner join (select list of 97 IDs) wanted_ids 
on all_records.id = wanted_ids.id
or all_records.lag1 = wanted_ids.id
or all_records.lag2 = wanted_ids.id
or all_records.lag3 = wanted_ids.id
or all_records.lag4 = wanted_ids.id
or all_records.lag5 = wanted_ids.id
or all_records.lead1 = wanted_ids.id
or all_records.lead2 = wanted_ids.id
or all_records.lead3 = wanted_ids.id
or all_records.lead4 = wanted_ids.id
or all_records.lead5 = wanted_ids.id
order by thedate, thetime;

答案 1 :(得分:0)

试试这个LOGIC,它与你的桌子不同,但你可以使用相同的LOGIC&得到你想要的东西。

;With CTE as 
(
select * 
 ,ROW_NUMBER() OVER (ORDER BY DateDt) AS RowNumber
 from mtT

), CTETop as
(
select top 5 *,'top' as section from CTE
order by RowNumber asc
),CTEBottom as 
(
select top 5 *,'bottom' as section from CTE
order by RowNumber desc
)
select * from CTETop

Union All

select * from CTEBottom

[DEMO]