Obter o segundo valor mais alto em uma tabela

14
id value
1   50
2   60
3   55

select max(value) from tablename;

Geralmente sabemos que teremos 60, mas preciso do próximo valor 55.

Como obtenho o valor 55 usando SQL?

Mahfuz Morshed
fonte

Respostas:

24

Supondo que o valor mais alto ocorra apenas uma vez, outra maneira seria usar OFFSET(SQL Server 2012 ou posterior):

SELECT * 
FROM tablename
ORDER BY column DESC 
OFFSET 1 ROW 
FETCH NEXT 1 ROW ONLY;
Renato Afonso
fonte
24

Para obter o segundo valor distinto mais alto da tabela, você pode usar

SELECT MIN(value)
FROM   (SELECT DISTINCT TOP (2) value
        FROM   tablename
        ORDER  BY value DESC)T
/*If only one distinct value return nothing. */
HAVING MIN(value) <> MAX(value);
Martin Smith
fonte
13

Uma solução genérica pode ser como abaixo:

;WITH CTE AS
(
    SELECT
        Col1
        , Col2
        , <AnyColumns>
        , ROW_NUMBER() OVER (ORDER BY <AnyColumns>) AS RowNum
    FROM <YourTable>
    WHERE <YourCondition>
)
SELECT *
FROM CTE
WHERE RowNum = 2 -- Or any condition which satisfies your problem

Aqui você também pode definir o intervalo como RowNum >= 10 AND RowNum <= 20. E ele fornecerá de 10 a 20 linhas com todas as colunas necessárias.

SwapnilBhate
fonte
7

Você tem o truque habitual, como:

select top 1 *
from (
    select top 2 *
    from my_table
    order by value desc
    ) t 
order by value asc 

Ou você também pode usar o CTE como:

with CTE as
(
select value, ROW_NUMBER() over(order by value desc) as ord_id
from my_table
)
select value
from CTE
where ord_id = 2

Ou, se você usar a versão recente do SQLServer (> = 2012), a função lag .

SELECT  top 1  lag(value, 1,0) OVER (ORDER BY value)  
FROM my_table
order by value desc
irimias
fonte
5

Eu farei assim:

SELECT MAX(value)
FROM tablename
WHERE value < (SELECT MAX(value)
               FROM tablename)
Amo
fonte
1

Você também pode usar a ROW_NUMBER()função de janelas. Se você deseja obter a 2ª entrada quando solicitado pelo seu valor-alvo, pode:

SELECT value 
FROM (
    SELECT 
        ROW_NUMBER() OVER (PARTITION BY NULL ORDER BY value DESC) as RN,
        value
    FROM my_table
) d
WHERE RN = 2

Agora, se você deseja obter o 2º valor mais alto e duplicar, pode agrupar pela entrada de valor para obter apenas valores distintos.

SELECT value 
FROM (
    SELECT 
        ROW_NUMBER() OVER (PARTITION BY NULL ORDER BY value DESC) as RN,
        value
    FROM my_table
    GROUP BY value
) d
WHERE RN = 2

Você deve poder modificar essa abordagem para incluir um MIN(id)na seleção interna se precisar conhecer o ID do primeiro registro com o segundo valor mais alto (supondo que você tenha um conjunto de dados com dois anos 60 e dois anos 55)

CodeMonkey
fonte
5
Para a segunda mais alta é mais fácil apenas substituir ROW_NUMBER()com DENSE_RANK()- você também terá todas as outras colunas gratuitamente. Não há necessidade de usar GROUP BY.
ypercubeᵀᴹ