有一个表T,id中有一个随机值,如果有一个select我们可以在输入中得到id的极值。 例如:
T.id =
12
34
76
89
1234
1254
6789
3456
对于输入我们给select id = 1254,作为输出我们必须得到两个值1234和6789
答案 0 :(得分:2)
您可以使用条件聚合:
select max(case when id < 1254 then id end) as prev,
min(case when id > 1254 then id end) as next
from t;
类似的方法会生成两行,但如果您有索引则效率更高:
select 'prev', max(id)
from t
where id < 1254
union all
select 'next', min(id)
from t
where id > 1254;
编辑:
我似乎错过了ids发生故障。在这种情况下,您需要假设有一个列指定数据的顺序。 SQL表表示无序集,因此没有下一个或上一个值。如果您有一个用于订购的列,则可以使用窗口函数处理此问题:
with n as (
select t.*, row_number() over (order by <ordering column goes here>) as seqnum
from t
)
select max(case when seqnum = theseqnum - 1 then id end) as prev_id,
max(case when seqnum = theseqnum + 1 then id end) as next_id
from (select n.*,
max(case when id = 1254 then seqnum end) as theseqnum
from n
) n
where seqnum = theseqnum - 1 or seqnum = thesequm + 1;
答案 1 :(得分:2)
你可以在下面这样做:
样本日期
CREATE TABLE #Test (ID INT)
INSERT INTO #Test VALUES (12),(34),(76),(89),(1234),(1254),(6789),(3456)
<强> INPUT 强>
DECLARE @var INT = 1234
<强> QUERY 强>
;WITH cte AS
(
SELECT Id,
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) rn1
FROM #Test t
)
SELECT PrevId, NextId
FROM cte
LEFT JOIN (
SELECT Id PrevId,
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) rn
FROM #Test t1
) previd ON cte.rn1 = previd.rn +1
LEFT JOIN (
SELECT Id NextId,
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) rn
FROM #Test t1
) nextid ON cte.rn1 = nextid.rn -1
WHERE cte.Id = @var
<强>输出强>
PrevId NextId
89 1254
<强>样本强>
您可以在 SQL FIDDLE
进行测试答案 2 :(得分:1)
您没有提到您正在使用的SQL Server版本。如果它是2012年以上,您可以使用LAG()和LEAD()函数来实现这一目标:
<强> LAG:强>
访问同一结果集中前一行的数据而不使用 在SQL Server 2012+中使用自联接。 LAG提供对行的访问 在当前行之前的给定物理偏移处。用这个 SELECT语句中的分析函数来比较中的值 前一行中包含值的当前行。
<强> LEAD:强>
访问同一结果集中后续行的数据而不使用 在SQL Server 2012+中使用自联接。 LEAD提供对行的访问 在当前行之后的给定物理偏移处。用这个 SELECT语句中的分析函数来比较中的值 当前行,其中包含下一行中的值。
以下是一个例子:
DECLARE @Test TABLE
(
ID INT
);
INSERT INTO @Test
VALUES (12)
, (34)
, (76)
, (89)
, (1234)
, (1254)
, (6789)
, (3456);
;WITH CTE (ID, Prev, Next, Extreme)
AS (
SELECT ID
, LAG(ID) OVER (ORDER BY (SELECT NULL))
, LEAD(ID) OVER (ORDER BY (SELECT NULL))
, MAX(ID) OVER ()
FROM @Test
)
SELECT *
FROM CTE
WHERE ID = 1234;
此查询返回
╔══════╦══════╦══════╦═════════╗
║ ID ║ Prev ║ Next ║ Extreme ║
╠══════╬══════╬══════╬═════════╣
║ 1234 ║ 89 ║ 1254 ║ 6789 ║
╚══════╩══════╩══════╩═════════╝
如lad2025所述,如果sql server optimizer决定使用并行性,那么这个以及回答良好的查询将会中断。
使用OPTION(MAXDOP 1)
提示可以解决它。它告诉sql server不要使用并行性。只有正确的方法才有列,您可以为数据集提供稳定的订单。