Attention: We are retiring the ASP.NET Community Blogs. Learn more >

SQL Puzzle #1 - Answer

Here's my solution to the puzzle in my previous post. If you haven't seen the challenge, go back and read that first.

Are you reading this before trying to solve the puzzle on your own? Unacceptable! Your IP is being logged! C'mon, give it a try! 

My Solution

I used 29 lines and 3 temp tables. It's reasonably straightforward - I set up a rank table (#temp), cross join it with the Student table to get ten rows for each student (a cartesian product), then join it to the grades table in order and select out the result.

The one little trick is the ranking in the selct for #temp3 - I used the GradeID as the tie-breaker if the student gets the same grade more than once. Without a tie-breaker, a duplicate score would result duplicating one Row number and  skipping the next (e.g. 1,2,3,4,5,5,7,8,9,10).

How would you solve this?  

use [test] go IF OBJECT_ID('tempdb..#temp') IS NOT NULL drop table #temp create table #temp (Row int) declare @counter int set @counter = 0 while @counter < 10 begin set @counter = @counter + 1 insert into #temp (Row) values (@counter) end IF OBJECT_ID('tempdb..#temp2') IS NOT NULL drop table #temp2 create table #temp2 (Row int, StudentID int) insert into #temp2 select Row, StudentID from Student, #temp order by StudentID, Row IF OBJECT_ID('tempdb..#temp3') IS NOT NULL drop table #temp3 select *, (SELECT COUNT(*) FROM Grade pt2 WHERE pt2.Grade + (.001*pt2.GradeID) >= pt.Grade + (.001*pt.GradeID) AND pt2.StudentID = pt.StudentID) AS Row into #temp3 from Grade pt order by StudentID, Grade desc select a.Row, a.StudentID, s.FirstName, s.LastName, b.Grade from #temp2 a left join #temp3 b on a.StudentID = b.StudentID and a.Row = b.Row inner join Student s on a.StudentID = s.StudentID drop table #temp drop table #temp2 drop table #temp3

3 Comments

  • Bit of a cheat using lots of sub-queries, but it does eliminate the temporary tables, or at least two of them anyway...

    USE [Test]
    GO

    IF OBJECT_ID('tempdb..#temp1') IS NOT NULL drop table #temp1
    CREATE TABLE #temp1 (row INT)

    DECLARE @counter INT
    SET @counter = 0
    WHILE @counter = pt.Grade + (.001*pt.GradeID) AND pt2.StudentID = pt.StudentID) AS Row from Grade pt) SQ1
    ON T.StudentID = SQ1.StudentID AND T.row = SQ1.row

    drop table #temp1

  • why not table variables?

  • I used temp tables rather than table variables or subqueries because I think it's a little easier to follow what's going on. You can comment out the "delete #temp" lines at the end and select the values to see what's going on.

    @haacked - So far it looks like Rob is the only one that passes, although I'm suspicious that he might have referenced the solution when he was writing his query. ;-)

Comments have been disabled for this content.