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
Published Thursday, November 02, 2006 12:22 AM by Jon Galloway
Filed under: ,

Comments

# re: SQL Puzzle #1 - Answer

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 < 10

BEGIN

 SET @counter = @counter + 1

 INSERT INTO #temp1 (Row) VALUES (@counter)

END

SELECT T.Row, T.StudentID, T.Firstname, T.LastName, SQ1.Grade

FROM (SELECT T.Row, S.StudentID, S.Firstname, S.Lastname FROM #temp1 T CROSS JOIN Student S) T

LEFT JOIN (select *, (SELECT COUNT(*) FROM Grade pt2 WHERE pt2.Grade + (.001*pt2.GradeID) >= 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

Thursday, November 02, 2006 5:27 AM by Rob

# re: SQL Puzzle #1 - Answer

why not table variables?

Thursday, November 02, 2006 11:15 AM by Peter

# Re: SQL Puzzle #1 - Answer

I say flunk them all.

Thursday, November 02, 2006 12:12 PM by haacked@gmail.com (Haacked)

# re: SQL Puzzle #1 - Answer

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. ;-)

Thursday, November 02, 2006 2:38 PM by Jon Galloway

# re: SQL Puzzle #1 - Answer

I did for the part that forms SQ1, as for the rest being broadly similar, there are only so many ways to skin a cat,... (It was more of an "after the fact can I beat what's there" kinda thing! ;-)

I could've used "SELECT 1 UNION SELECT 2 UNION SELECT 3.........." instead of populating the temp table, but that just looks fantastically ugly.

One thing that's worth mentioning as there is an explicit DROP TEMP (which I did solely so the line-count would be a more accurate comparison) is that these shouldn't be in production sprocs as they can/do (can never remember which!) cause recompiles which will hurt perf.

Thursday, November 02, 2006 5:53 PM by Rob

Leave a Comment

(required) 
(required) 
(optional)
(required)