Click here to monitor SSC

Lionel Clarke

Software Engineer - Red Gate Software

A Sql Puzzle for you all

Published Friday, October 28, 2005 2:10 PM

/*
To try and help everyone get a little better at sql I am setting a
little puzzle for you all to do based on a problem that Richard had
with the check for updates site.

The puzzle is simple. We have a version table that holds all the version
of all our products that we release. The version number is represented
with four numbers a,b,c and d where a is the major version and the other
letters represent which sub version it is. So the puzzle is to write a
query to find the latest build for each major version. So in result from
the data bellow should be.

a           b           c           d          
----------- ----------- ----------- -----------
1           2           2           4
2           3           1           7
3           2           1           5

You are only alowed to use one SQL statment and definantly no cursers. Also
no solutions that use any strings!!!!!. ALSO a, b, c or d could all potentally be
Int32.MaxValue so make sure your solutions don't overflow!!!!!!!

Email solutions to me.

Here is some example data to get you started
*/
DECLARE @Version TABLE
(
    a int,
    b int,
    c int,
    d int
)

INSERT INTO @Version(a, b, c, d)
    SELECT 1,1,1,23
INSERT INTO @Version(a, b, c, d)
    SELECT 1,2,1,1
INSERT INTO @Version(a, b, c, d)
    SELECT 1,2,2,4
INSERT INTO @Version(a, b, c, d)
    SELECT 2,1,1,1
INSERT INTO @Version(a, b, c, d)
    SELECT 3,1,1,2
INSERT INTO @Version(a, b, c, d)
    SELECT 2,1,2,8
INSERT INTO @Version(a, b, c, d)
    SELECT 2,1,3,4
INSERT INTO @Version(a, b, c, d)
    SELECT 2,2,1,2
INSERT INTO @Version(a, b, c, d)
    SELECT 2,2,3,1
INSERT INTO @Version(a, b, c, d)
    SELECT 2,2,4,6
INSERT INTO @Version(a, b, c, d)
    SELECT 2,3,1,7
INSERT INTO @Version(a, b, c, d)
    SELECT 3,2,1,5
by James

Comments

 

Philippe said:

SELECT a, b,c,d from @version Ta
where Ta.b = (select max(b) from @version Tb where Ta.a=Tb.a)
and Ta.c = (select max(c) from @version Tc where Tc.a=Ta.a and Tc.b=ta.b)
and Ta.d = (select max(d) from @version Td where Td.a=Ta.a and Td.b=ta.b and Td.c=Ta.c)

select Ta.a, Ta.b, Ta.c, Ta.d
from @Version Ta
where not exists( SELECT 0 from @version Tb WHERE ta.a = Tb.a and ta.b < Tb.b)
and not exists( SELECT 0 from @version Tc WHERE Ta.a = Tc.a and Ta.b = Tc.b AND Ta.c < Tc.c)
and not exists( SELECT 0 from @version Td WHERE Ta.a = Td.a and Ta.b = Td.b AND Ta.c = Td.c AND Ta.d <Td.d)

November 22, 2005 3:53 PM
 

Lionel said:

Both those look good. Do people think that the comments is a good place to post solutions? I have a number of good solutions for this particular puzzle from various people :)

Lionel
November 22, 2005 4:00 PM
 

Adam said:

I was wondering where the answers were going to be posted. Comments seems like as good a place as any.
November 23, 2005 9:59 AM
 

Eric said:

According to exection planer, the one above that uses exists is far superior to the other solution. However, both of them beat my solution:

SELECT A.a, B.b, C.c, D.d
FROM #Version A JOIN (SELECT Sub1.a,
Max(Sub1.b) AS b
FROM #Version Sub1
GROUP BY Sub1.a) B ON A.a = B.a
JOIN (SELECT Sub2.a, Sub2.b,
Max(Sub2.c) AS c
FROM #Version Sub2
GROUP BY Sub2.a,
Sub2.b) C ON B.a = C.a AND B.b = C.b
JOIN (SELECT Sub3.a, Sub3.b, Sub3.c,
Max(Sub3.d) AS d
FROM #Version Sub3
GROUP BY Sub3.a,
Sub3.b,
Sub3.c) D ON C.a = D.a AND C.b = D.b AND C.c = D.c
GROUP BY A.a, B.b, C.c, D.d
June 13, 2006 9:17 PM
 

Eric said:

It turns out, if you put a composite key on a,b,c,d then mine and the "not exists" solution come up equal in execution planner.

So, if you properly index your data then you can remain dumb and SQL server will figure out the best way for you. :)
June 14, 2006 1:40 PM
 

Celko said:

Why make it so had?

SELECT a, b, c, d
 FROM (SELECT a, b, c, d,
       ROW_NUMBER() OVER(PARTITION BY a ORDER BY b DESC, c DESC, d DESC) AS latest
         FROM Version) AS X(a, b, c, d, latest)
WHERE latest = 1;
December 21, 2007 10:08 AM
 

AlexM said:

Even less code:

SELECT TOP 1 WITH TIES *
FROM @version
ORDER BY ROW_NUMBER() over (PARTITION BY a ORDER BY b DESC, c DESC, d DESC)

(much like to the solution of Celko, but I came to it before reading comments)
March 21, 2008 7:35 AM
 

Fun with SQL (games, painting, puzzles) « 1st blog, pre-beta version… said:

January 24, 2010 2:03 AM
You need to sign in to comment on this blog
<October 2005>
SuMoTuWeThFrSa
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345
How to Kill a Company in One Step or Save it in Three
 The majority of companies that suffer a major data loss subsequently go out of business. David Wesley... Read more...

Migrating from OCS 2007 R2 to Lync: Part 4
 Having migrated the rest of our users and legacy resources across and started getting ready to... Read more...

Automated Script-generation with Powershell and SMO
 In the first of a series of articles on automating the process of building, modifying and copying SQL... Read more...

Seth Godin: Big in the IT Business
 Seth Godin has transformed our understanding of marketing in IT. He invented the concept of 'permission... Read more...

Using SQL Test Database Unit Testing with TeamCity Continuous Integration
 With database applications, the process of test and integration can be frustratingly slow because so... Read more...