T_SQL查询极值

时间:2015-10-16 10:37:26

标签: sql sql-server tsql select

有一个表T,id中有一个随机值,如果有一个select我们可以在输入中得到id的极值。 例如:

T.id = 
12
34
76
89
1234
1254
6789
3456

对于输入我们给select id = 1254,作为输出我们必须得到两个值1234和6789

3 个答案:

答案 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不要使用并行性。只有正确的方法才有列,您可以为数据集提供稳定的订单。