views:

70

answers:

3

I have two tables:

Table1 = Schools
    Columns: id(PK), state(nvchar(100)), schoolname

Table2 = Grades
    Columns: id(PK), id_schools(FK), Year, Reading, Writing...

I would like to develop a query to find the schoolname which has the highest grade for Reading.

So far I have the following and need help to fill in the blanks:

SELECT Schools.schoolname, Grades.Reading
FROM Schools, Grades
WHERE Schools.id = (* need id_schools for max(Grades.Reading)*)
A: 

This should do it

select * from Schools as s
where s.id=(
select top(1) id_schools from grades as g
order by g.reading desc)
josephj1989
should I be using `in` instead of `=`?
Seth
you can use = as top(1) returns only one record
josephj1989
if there are multiple schools with the same (maximum) grade wouldn't this return only 1 row?
potatopeelings
+1  A: 

Here's how I solve this sort of problem without using a subquery:

SELECT s.*
FROM Schools AS s
JOIN Grades AS g1 ON g1.id_schools = s.id
LEFT OUTER JOIN Grades AS g2 ON g2.id_schools <> s.id
  AND g1.Reading < g2.Reading
WHERE g2.id_schools IS NULL

Note that you can get more than one row back, if more than one school ties for highest Reading score. In that case, you need to decide how to resolve the tie and build that into the LEFT OUTER JOIN condition.


Re your comment: The left outer join looks for a row with a higher grade for the same school, and if none is found, all of g2.* columns will be null. In that case, we know that no grade is higher than the grade in the row g1 points to, which means g1 is the highest grade for that school. It can also be written this way, which is logically the same but might be easier to understand:

SELECT s.*
FROM Schools AS s
JOIN Grades AS g1 ON g1.id_schools = s.id
WHERE NOT EXISTS (
    SELECT * FROM Grades g2 
    WHERE g2.id_schools <> s.id AND g2.Reading > g1.Reading)

You say it's not working. Can you be more specific? What is the answer you expect, and what's actually happening, and how do they differ?


edit: Changed = to <> as per suggestion in comment by @potatopeelings. Thanks!

Bill Karwin
Thanks Bill. However, this query isn't working what is the reason for `g2.id_schools IS NULL`?
Seth
The query is returning multiple results ( which is possible ). However, I know 1500 results is not correct and when I do a spot check on the school row it definitely doesn't correspond to the maximum grade. The expected answer should only be 1 result. Are there any pre-requisites for this query to work correctly?
Seth
Well then you can try the answer from @josephj if that gives the right answer.
Bill Karwin
Bill... I think you want g2.id_schools = s.id in your second code sample to be g2.id_schools <> s.id. = would return all rows from the join
potatopeelings
@potatopeelings - good spot, that got the max reading result for the entire set
Seth
Thanks @potatopeelings, I've edited the above queries.
Bill Karwin
+1  A: 
SELECT 
     Schools.schoolname, 
     Grades.Reading 
FROM 
     Schools INNER JOIN Grades on Schools.id = Grades.id_schools
WHERE 
     Grades.Reading = (SELECT MAX(Reading) from Grades)
potatopeelings
this works however, I still have to use `IN` not `=` otherwise I get an error.
Seth
that's strange. could you do a "SELECT MAX(Reading) from Grades" and check what is returned.By the way, this might be more expensive because of the sub-query. i don't know enough about performance tuning to compare this vs. if you use joins (Bill Karwin's answer)
potatopeelings
that returns the max(reading) value. I am using SQL Server Express and a SQL Server Compact file to store all the data.
Seth
sorry, i don't know why this would need a IN instead of an =. I hope one of the other answers works out (in a non-strange way, that is)
potatopeelings