Lionel Clarke

Software Engineer - Red Gate Software

Sql Puzzle 2

Published Friday, November 04, 2005 4:46 PM

/*
Todays puzzle comes from Andras who incudentally got the best
solution so far to the last puzzle.

We have two tables a letters table and a numbers table. The letters table
is a letter followed by three numbers. The idea is to write a query that
returns all the letters that have all numbers listed in the numbers table.
This is probably best explaind in an example. so the Letters table contains

a,1,2,3
a,4,5,6
a,4,5,6
b,1,2,3
c,1,2,3
c,4,5,3
d,1,9,4
d,2,8,5
d,3,7,6
d,4,6,7
e,1,2,3
e,4,5,6
e,4,5,6
e,4,6,7

The numbers table contains.
1,2,3
4,5,6
4,5,6

So for a letter to be selected it must have three entries in the letters table
One with 1,2,3. A second with 4,5,6. A third with 4,5,6. So if there is a
duplicate in the numbers table there must be a duplicate in the letters table.
In the example above the result will be a and e. A is returned as it has
exactally the three numbers following it that are in the numbers table. E is
also returned as it also has all of the entries in the numbers table and it
doesn't matter if there are extra ones.

The expected result from the data bellow should be:

Letter
------
a
e

Happy coding :)
*/
SET NOCOUNT ON

DECLARE @Letters TABLE
(
    Letter Char(1) NOT NULL,
    NumberA INT NOT NULL,
    NumberB INT NOT NULL,
    NumberC INT NOT NULL
)
DECLARE @Numbers TABLE
(
    NumberA INT NOT NULL,
    NumberB INT NOT NULL,
    NumberC INT NOT NULL
)

INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'a', 1, 2, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'a', 2, 3, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'a', 1, 2, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'a', 1, 3, 4

INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'b', 1, 2, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'b', 2, 3, 3

INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'c', 1, 2, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'c', 1, 2, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'c', 1, 2, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'c', 1, 2, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'c', 1, 2, 3

INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'd', 6, 5, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'd', 3, 2, 4
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'd', 7, 2, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'd', 1, 4, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'd', 1, 2, 3

INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'e', 1, 2, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'e', 2, 3, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'e', 1, 2, 3

INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'f', 1, 2, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'f', 2, 3, 8
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'f', 7, 3, 3
INSERT INTO @Letters(Letter, NumberA, NumberB, NumberC)
    SELECT 'f', 1, 2, 3



INSERT INTO @Numbers(NumberA, NumberB, NumberC)
    SELECT 1, 2, 3
INSERT INTO @Numbers(NumberA, NumberB, NumberC)
    SELECT 1, 2, 3
INSERT INTO @Numbers(NumberA, NumberB, NumberC)
    SELECT 2, 3, 3

SET NOCOUNT OFF
by James

Comments

 

AlexM said:

-- Hi. This is my solution to the puzzle. It seems to be stupid, but nevertheless it seems to be working :-)
SELECT L.Letter
FROM
(SELECT N.NumberA, N.NumberB, N.NumberC, N = COUNT(*)
FROM @Numbers N
GROUP BY N.NumberA, N.NumberB, N.NumberC) N
INNER JOIN (SELECT L.Letter, L.NumberA, L.NumberB, L.NumberC, N = COUNT(*)
FROM @Letters L
GROUP BY L.letter, L.NumberA, L.NumberB, L.NumberC) L ON N.NumberA = L.NumberA AND N.NumberB = L.NumberB AND N.NumberC = L.NumberC
AND  N.N = L.N
GROUP BY L.Letter
HAVING COUNT(*) = (SELECT COUNT(*) FROM (SELECT NumberA FROM @Numbers GROUP BY NumberA, NumberB, NumberC) T)
ORDER BY 1

-- The 2nd solution is shorter, but it can only be used in case we're really sure there are letters that satisfy task condition, otherwise the result is incorrect:
SELECT TOP 1 WITH TIES L.Letter
FROM
(SELECT L.Letter, L.NumberA, L.NumberB, L.NumberC, N = COUNT(*)
FROM @Letters L
GROUP BY L.letter, L.NumberA, L.NumberB, L.NumberC) L
INNER JOIN (SELECT N.NumberA, N.NumberB, N.NumberC, N = COUNT(*)
FROM @Numbers N
GROUP BY N.NumberA, N.NumberB, N.NumberC) N ON N.NumberA = L.NumberA AND N.NumberB = L.NumberB AND N.NumberC = L.NumberC
AND  N.N = L.N
GROUP BY L.Letter
ORDER BY COUNT(*) DESC
March 24, 2008 3:43 PM
 

ORKO said:

IN oracle i would solve the problem like this:
select A.letter
   from
   (select letter,numberA,numberB,numberC,count(*)cnt
   from letters
   group by letter,numberA,numberB,numberC
   )A,
   
   (  
   select NumberA, NumberB, NumberC,count(*) cnt
   from
   numbers
   group by NumberA, NumberB, NumberC
    )B
 where
    A.numberA=B.numberA
and     A. numberB= B. numberB
and     A.numberC= B.numberC
and     A.cnt >= B.cnt
group by a.letter
having count(*)=(select count(*) from (select distinct NumberA, NumberB, NumberC from numbers))
order by 1                



March 29, 2008 7:09 AM
 

SunilDutt N said:

How about this ???

SELECT DISTINCT Letter FROM @Letters L
INNER JOIN @Numbers N ON L.NumberA = N.NumberA AND L.NumberB = N.NumberB AND L.NumberC = N.NumberC
May 27, 2009 5:58 AM
 

SunilDutt N said:



SELECT DISTINCT Q.Letter FROM
(
SELECT Letter,L.NumberA,L.NumberB, L.NumberC
FROM @Letters L INNER JOIN @Numbers N ON N.NumberA = L.NumberA AND N.NumberB = L.NumberB AND N.NumberC = L.NumberC
GROUP BY Letter,L.NumberA,L.NumberB, L.NumberC
HAVING (COUNT(*) >= (SELECT COUNT(*) FROM @Numbers WHERE NumberA = L.NumberA AND NumberB = L.NumberB AND NumberC = L.NumberC))
) Q
GROUP BY Q.Letter
HAVING COUNT(Letter) = (SELECT COUNT(*) FROM @Numbers )
May 27, 2009 6:13 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


















<November 2005>
SuMoTuWeThFrSa
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910
Microsoft Office Communications Server 2007 R2 – Part II
  Once you have set up Office Communication Server 2007 R2 to provide IM within the rganisation, the... Read more...

Mission Critical: Database Design
 There is nothing like a checklist to make sure you've completed all the tasks in designing a database,... Read more...

SQL Server Intellisense VS. Red Gate SQL Prompt
 Fabiano Amorim is hooked on today's Integrated Development Environments with built-in Intellisense, so... Read more...

Doug Crockford: Geek of the Week
  Doug Crockford is the man behind JavaScript Object Notation (JSON). He is a well-known critic of XML... Read more...

Raw Materials: Mirror, Mirror, on the Desk
 Seeing ourselves as we see ourselves. Read more...