我必须选择小于给定 id 且大于给定 id 的 2 个值。我已经尝试过这个查询,但有没有更好的方法来做到这一点
小提琴Sql
Begin
declare @rootValue int
declare @repID int
set @repID = 2
set @rootValue = (select Id from tblLookups where Id = @repID)
declare @rootMinusTwo int
declare @rootPlusTwo int
set @rootMinusTwo = (select count(*) from tblLookups where Id < @rootValue)
set @rootPlusTwo = (select count(*) from tblLookups where Id > @rootValue)
if @rootMinusTwo >= 2 and @rootPlusTwo >= 2
Begin
select *
from tblLookups
where Id between @rootValue - 2 and @rootValue + 2
End
else if @rootMinusTwo < 2 and @rootPlusTwo >= 2
select *
from tblLookups
where Id = @repID
union
select *
from tblLookups
where Id < @rootValue
union
select top (4 - @rootMinusTwo) *
from tblLookups
where Id > @rootValue
else if @rootMinusTwo >= 2 and @rootPlusTwo < 2
select *
from tblLookups
where Id = @repID
union
select *
from tblLookups
where Id > @rootValue
union
select top(4 - @rootPlusTwo) *
from tblLookups
where Id < @rootValue
else if @rootMinusTwo < 2 and @rootPlusTwo < 2
select *
from tblLookups
where Id = @repID
union
select *
from tblLookups
where Id < @rootValue
union
select *
from tblLookups
where Id > @rootValue
End
Run Code Online (Sandbox Code Playgroud)
我忘了在任何时候添加一些东西,如果有那么多满足条件的记录,那么应该有 5 条记录。
例子
ID 是 1,2,3,4,5 如果我提供 2 那么它也应该返回 5
相当令人费解,但应与下面的值工作,并返回2行@repid,与行@repid和2行以上的值@repid(假设id是一个独特的密钥)。
如果低于或高于 2 个值,则查询将从另一侧获取更多。总共最多返回 5 行。
注:在ORDER BY需要。所有三个(不是第 4 个,只有当您需要按特定顺序的结果时):
with a as
( select top (4)
*, rnk = row_number() over (order by id desc)
from tblLookups
where Id < @repID
order by id desc
),
b as
( select top (5)
*, rnk = row_number() over (order by id) - 1
from tblLookups
where Id >= @repID
order by id
),
c as
( select top (5) *
from
( select *
from a
union all
select *
from b
) x
order by rnk
)
select *
from c
order by id ;
Run Code Online (Sandbox Code Playgroud)
在SQLfiddle测试。
以下基本上是您的算法,但作为单个语句实现:
WITH ranked_and_counted AS (
SELECT
ID,
r = ROW_NUMBER() OVER (ORDER BY ID ASC),
c = COUNT(*) OVER ()
FROM
dbo.tblLookups
),
ranked_and_counted_and_r0 AS (
SELECT
*,
r0 = MAX(CASE ID WHEN @ID THEN r END) OVER ()
FROM
ranked_and_counted
)
SELECT
ID
FROM
ranked_and_counted_and_r0
WHERE
r >= CASE WHEN r0 > c - 2 THEN c - 4 ELSE r0 - 2 END
AND
r <= CASE WHEN r0 < 1 + 2 THEN 1 + 4 ELSE r0 + 2 END
;
Run Code Online (Sandbox Code Playgroud)
第一个 CTE,ranked_and_counted计算行数和总行数。
第二个 CTE,ranked_and_counted_and_r0确定与指定@ID.
主查询使用获取的值来获取所需的行:
如果参考行号 ( r0) 是表中最后两行之一,则当前行号 ( r) 必须大于或等于行数 ( c) 减四(即必须是最后五行之一),否则应大于或等于参考数字减二;
如果参考行是前两行之一,则当前行号不得大于五,否则应小于或等于参考号加二。
该查询可以在SQL Fiddle进行测试。(演示借用了ypercube的设置。)
| 归档时间: |
|
| 查看次数: |
455 次 |
| 最近记录: |