简体   繁体   中英

How to get the Highest, then the lowest, then the 2nd higest, and then the 2nd lowest value and so on from a table

I've a question, how can I get the highest value, then the lowest value, then the second highest value from a table.

For example: in the table

Name        Value
----------------------
Apple        2
Pear         3
Pineapple    6
Mango        7
Kiwi         1

Result should look like this:

Name           Value
-----------------------
Mango           7
Kiwi            1
Pineapple       6
Apple           2
Pear            3

Thanks!

I'm assuming the tsqlt tag was meant to be tsql , and further that this implies that this is for SQL server:

;with Numbered as (
    select Name,Value,
        ROW_NUMBER() OVER (ORDER BY Value DESC) as rnDesc,
        ROW_NUMBER() OVER (ORDER BY Value ASC) as rnAsc
    from
        @t
), MixedNumbered as (
    select
        Name,Value,
        CASE WHEN rnDesc < rnAsc THEN rnDesc ELSE rnAsc END as rnFin,
        rnAsc,
        rnDesc
    from
        Numbered
)
select Name,Value from MixedNumbered order by rnFin,rnDesc

This works by finding the row numbers whilst considering the list sorted both highest-to-lowest and lowest-to-highest (in Numbered , rnDesc and rnAsc ). We then take the lowest row number that was achieved when considering either of these orderings ( MixedNumbered , rnFin ).

This should then, produce two rows with an rnFin equal to 1, two rows with it equal to 2, and so on; pairing the n th highest and n th lowest rows until we reach the middle of the set.

We then use this to sort the final result set - but use the position obtained by considering the values sorted highest-to-lowest ( rnDesc ) as the tie breaker between each pair of rows with the same rnFin value. This means, for each pair, that the higher valued row will appear first.

To reverse the result (lowest first, then highest, the second lowest, second highest, etc), we need only change the final ORDER BY clause to rnFin,rnAsc .

This assigns the number 2 to the largest row, 3 to the smallest, 4 to the second largest, and so on.

select  *
from    (
        select  1 + 2 * row_number() over (order by Value asc) as rnAsc
        ,       2 * row_number() over (order by Value desc) as rnDesc
        ,       t1.*
        from    Table1 t1
        ) SubQueryAlias
order by
        case
        when rnDesc < rnAsc then rnDesc
        else rnAsc
        end

Example at SQL Fiddle.

A great question! Please check my try:

SELECT Name,Value
FROM(
    SELECT *, MAX(Rnum) OVER() mx, MAX(Rnum) OVER()/2.0 hf FROM(
        SELECT *, ROW_NUMBER() OVER(ORDER BY value DESC) Rnum From @tbl
    )x
)xx
ORDER BY CASE WHEN Rnum-hf<=0 THEN Rnum ELSE mx-Rnum+1 END, Rnum

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM