Question

I need help with a t-sql query.

I have a table with this structure:

id  |  OverallRank  |  FirstRank  |  SecondRank  |  Nrank..
1   |       10      |    20       |     30       |    5
2   |       15      |    24       |     12       |    80
3   |       10      |    40       |     37       |    12

I need a query that produces this kind of result:

When id: 1

id  |  OverallRank  |  BestRankLabel  |  BestRankValue  |  WorstRankLabel  | WorkRankValue
1   |     10        |    SecondRank   |        30       |     Nrank        |       5

When id: 2

id  |  OverallRank  |  BestRankLabel  |  BestRankValue  |  WorstRankLabel  | WorkRankValue
1   |     15        |    FirstRank    |        24       |     SecondRank   |       12

How can I do it?

Thanks in advance

Was it helpful?

Solution

with cte(id, RankValue,RankName) as (
            SELECT id, RankValue,RankName
            FROM 
                        (SELECT id,  OverallRank,  FirstRank,  SecondRank, Nrank 
                        FROM ##input) p
            UNPIVOT
                        (RankValue FOR RankName IN 
                                    (OverallRank,  FirstRank,  SecondRank, Nrank)
            )AS unpvt)
select t1.id, max(case when RankName = 'OverallRank'  then RankValue else null end) as OverallRank,
        max(case when t1.RankValue = t2.MaxRankValue then RankName else null end) as BestRankName,
        MAX(t2.MaxRankValue) as BestRankValue,
        max(case when t1.RankValue = t3.MinRankValue then RankName else null end) as WorstRankName,
        MAX(t3.MinRankValue) as WorstRankValue
        from cte as t1
        left join (select id, MAX(RankValue) as MaxRankValue from cte group by id) as t2 on t1.id = t2.id
        left join (select id, min(RankValue) as MinRankValue from cte group by id) as t3 on t1.id = t3.id
    group by t1.id

Working good with your test data. You should only edit RankName IN (OverallRank, FirstRank, SecondRank, Nrank) by adding right columns' names.

OTHER TIPS

CASE 
   WHEN OverallRank > FirstRank and OverallRank > FirstSecondRand and  OverallRank > nRank THEN 'OverallRank' 
   WHEN FirstRank > OverallRank ... THEN 'FirstRank' 
END

This kind of query is why you should normalise your data.

declare @id int, @numranks int
select @id = 1, @numranks = 3 -- number of Rank columns

;with cte as    
(   
    select *
    from
    (
        select *,
            ROW_NUMBER() over (partition by id order by rank desc) rn
        from
        (
        select * from YourBadlyDesignedTable
            unpivot (Rank for RankNo in (FirstRank, SecondRank, ThirdRank))u -- etc
        ) v2
    ) v1
    where id=@id and rn in (1, @numranks)
) 
    select 
        tMin.id, 
        tMin.OverallRank,       
        tMin.RankNo as BestRankLabel,
        tMin.Rank as BestRankValue,
        tMax.RankNo as WorstRankLabel,
        tMax.Rank as WorstRankValue
    from (select * from cte where rn=1) tMin
        inner join (select * from cte where rn>1) tMax
            on tMin.id = tmax.id

You can take out the id = @id if you want all rows.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top