Mr.Softy
Mr.Softy

Reputation: 37

Sql getting MAX and MIN values based on two columns for the ids from two others

I'm having difficulties figuring a query out, would someone be able to assist me with this? Problem: 4 columns that represent results for the 2 separate tests. One of them taken in UK and another in US. Both of them are the same test and I need to find the highest and lowest score for the test taken in both countries. I also need to avoid using subqueries and temporary tables. Would appreciate theoretical ideas and actual solutions for the problem.

The table looks like this:

 ResultID   Test_UK   Test_US   Test_UK_Score   Test_US_Score
   1          1         2       48              11
   2          4         1       21              24
   3          3         1       55              71
   4          5         6       18              78
   5          7         4       19              49
   6          1         3       23              69
   7          5         2       98              35
   8          6         7       41              47

The desired results I'm looking for:

TestID  HighestScore  LowestScore
   1       71             23
   2       35             11
   3       69             55
   4       49             21
   5       98             18
   6       78             41
   7       47             19

I tried implementing a case of comparison, but I still ended up with subquery to pull out the final results. Also tried union, but it ends up in a sub query again. As far as I can think it shoul be a case when then query, but can't really come up with the logic for it, as it requires to match the ID's of the tests. Thank you! What I've tried and got the best results (still wrong)

select v.TestID,
    max(case when Test_US_Score > Test_UK_Score then Test_UK_Score else null end) MaxS, 
    min(case when Test_UK_Score > Test_US_Score then Test_US_Score else null end) MinS
FROM ResultsDB rDB CROSS APPLY
    (VALUES (Test_UK, 1), (Test_US, 0)
    ) V(testID, amount)
GROUP BY v.TestID

Extra

The answer provided by M. Kanarkowski is a perfect solution. I'm no expert on CTE, and a bit confused, how would it be possible to adapt this query to return the result ID of the row that min and max were found.

something like this:

TestID Result_ID_Max Result_ID_Min
  1          3              6
  2          7              1 
  3          6              3 

Extra 2

The desired results of the query would me something like this. The two last columns represent the IDs of the rows from the original table where the max and min values were found.

TestID HighestScore LowestScore Result_ID_Of_Max Result_ID_Of_Min
  1         71           23            3              6
  2         35           11            7              1 
  3         69           55            6              3 

Upvotes: 0

Views: 1322

Answers (1)

M. Kanarkowski
M. Kanarkowski

Reputation: 2195

For example you can use union to have results from both countries togehter and then just pick the maximum and the minimum for your data.

with cte as (
    select Test_UK as TestID, Test_UK_Score as score from yourTable
    union all 
    select Test_US as TestID, Test_US_Score as score from yourTable
)
select
    TestID
    ,max(score) as HighestScore
    ,min(score) as LowestScore
from cte
group by TestID
order by TestID

Extra: I assumed that you want to have the additional column with the previous result. If not just take the above select and replace Test_UK_Score and Test_US_Score with ResultID.

with cte as (
    select Test_UK as TestID, Test_UK_Score as score, ResultID from yourTable
    union all 
    select Test_US as TestID, Test_US_Score as score, ResultID from yourTable
)
select
    TestID
    ,max(score) as HighestScore
    ,min(score) as LowestScore
    ,max(ResultID) as Result_ID_Max
    ,min(ResultID) as Result_ID_Min
from cte
group by TestID
order by TestID

Upvotes: 1

Related Questions