Yesterday we looked at Puzzle and I did got great response to this question. Very interestingly not many got it right. First go through the puzzle first and then come back here and read answer.
Read Original Interview Question and Puzzle.
Question: Select all the person from table PersonColor who have same color as ColorCode or have more colors than table ColorCode.
UPDATE: Following solution is written with assumption that in SelectedColors table Name and ColorCode are Primary Key. This requirement was not specified in original question.
/*Answer to Interview Question*/
SELECT Name
FROM PersonColors pc
INNER JOIN SelectedColors sc ON sc.ColorCode = pc.ColorCode
GROUPÂ BY pc.Name
HAVING COUNT(pc.ColorCode)Â >=Â (SELECT COUNT(ColorCode) FROM SelectedColors)
GO
If you want to download complete script for this interview question. Please download it from here.
Complete script of the puzzle is also listed here.
USE AdventureWorks
GO
/*Create First Table PersonColors*/
CREATEÂ TABLE PersonColors (Name VARCHAR(100), ColorCode VARCHAR(100))
GO
INSERTÂ INTO PersonColors (Name,ColorCode)
VALUES ('Tom','Red'),('Tom','Blue'),('Tom','Green'),('Tom','Brown'),
('Mike','Red'),('Mike','Blue'),
('James','Green'),('James','Brown'),
('Joe','Red'),('Joe','Blue'),('Joe','Green'),
('Matt','Brown')
GO
SELECT *
FROM PersonColors
GO
/*Create Second Table SelectedColors*/
CREATEÂ TABLE SelectedColors (ColorCode VARCHAR(100))
GO
INSERTÂ INTO SelectedColors (ColorCode)
VALUES ('Red'),('Blue'),('Green')
SELECT *
FROM SelectedColors
GO
/*Answer to Interview Question*/
SELECT Name
FROM PersonColors pc
INNER JOIN SelectedColors sc ON sc.ColorCode = pc.ColorCode
GROUPÂ BY pc.Name
HAVING COUNT(pc.ColorCode)Â >=Â (SELECT COUNT(ColorCode) FROM SelectedColors)
GO
*Clean up DATABASE*/
DROPÂ TABLE PersonColors
DROPÂ TABLE SelectedColors
GO
Let me know your opinion about this puzzle.
Reference : Pinal Dave (https://blog.sqlauthority.com)
25 Comments. Leave new
Your solution is incorrect, as there’s no unique constraint. If you insert a person with a sufficient number of rows with colors not in SelectedColors, they will be in your result set but should not be according to your specifications.
Never mind I’m wrong :)
What’s makes this question a good one is that I used this answer in real-life in a report query a few months back.
Hi Dave,
I just looked into the site and recognized the style of insertion into the table like this
INSERT INTO PersonColors (Name,ColorCode)
VALUES (‘Tom’,‘Red’),(‘Tom’,‘Blue’),(‘Tom’,‘Green’),(‘Tom’,‘Brown’),
(‘Mike’,‘Red’),(‘Mike’,‘Blue’),
(‘James’,‘Green’),(‘James’,‘Brown’),
(‘Joe’,‘Red’),(‘Joe’,‘Blue’),(‘Joe’,‘Green’),
(‘Matt’,‘Brown’)
As all in my past I used to insert only one record at a time. And I was amazed at looking this that we can insert multiple records with in a single insert statement. But sadly, my it failed in my machine. The more interesting is I accidentally inserted a duplicate record into the SelectedColors table with the value ‘Red’ two times. I tried to delete only the duplicate. But cannot do that without deleting the ‘Red’ items. I tried in the GUI grid also to delete only one record. That failed to do this. Is there any work around for this rather than deleting all the records.
Wow, I’m just excited that I got the same answer! :)
That is an interesting puzzle, I’ve never had that sort of problem before “in real life” but it was fun.
I’m a newer reader to your blog, but do you have additional T-SQL puzzles like that (or in general)?
Thank you!
The posted answer will fail if there are multiple identical rows i.e. three rows that say Mark, Green. Mark will appear even though he only has one of the colors…
doh! I just read the update about the primary key.
SELECT distinct Name
FROM #PersonColors PC
INNER JOIN #SelectedColors SC on
SC.ColorCode=PC.ColorCode
Group by Name
HAving Count(PC.ColorCode) >=
(Select Count(1) from #SelectedColors)
wow.. that’s very good question.
i got same answer, please give me some more this type of question so that i can improve my knowledge.
i try this query
select name from PersonColors
where colorcode in(select colorcode from SelectedColors)
group by name
is it correct please reply…
If there is a primary key on Name and ColorCode I’m having trouble understanding why the having clause uses greater than or equal. Shouldn’t it be just equal?
DECLARE @cnt int
SELECT @cnt = COUNT(distinct colorcode) FROM selectedcolors
SELECT NAME FROM (
SELECT NAME,COUNT(DISTINCT scl.ColorCode) ColorCode FROM PersonColors n
INNER JOIN SelectedColors scl ON n.ColorCode = scl.ColorCode
GROUP BY NAME
HAVING COUNT(DISTINCT scl.ColorCode) = @cnt
) Q
select P.Name from personcolors P inner join selectedcolors S on P.colorcode=s.colorcode
group by P.Name
having COUNT(*)= (select COUNT(*) from selectedcolors)
HI.
pinaldave sorry to say but your answer is not correct…
Take a look:
If you run this:
delete from personcolors where name=’Tom’ and ColorCode=’Red’;
insert into personcolors values(‘Tom’, ‘Blue’);
The person Tom has three colors: green, brown and blue. Right now this user should not appear on the result set because he’s missing red color. Guess what? Running your query he is still shown on the result set (because he has two blue lines) :(
For this query to work it should be written like this:
SELECT Name
FROM PersonColors pc
INNER JOIN SelectedColors sc ON sc.ColorCode = pc.ColorCode
GROUP BY pc.Name
HAVING COUNT(distinct pc.ColorCode) = (SELECT COUNT(ColorCode) FROM SelectedColors)
The only difference is that i’m using COUNT(distinct pc.ColorCode).
My first solution was pretty much like yours, but after awhile I relized that it was not correct :-D
I’m a great fan of your blog
Greetings from Portugal ;-)
Leandro Nunes
@Leandro
“Following solution is written with assumption that in SelectedColors table Name and ColorCode are Primary Key. This requirement was not specified in original question.”
@Brian Tkatch
Sorry, I missed that. But assuming that there ia no need to have the greater or equal comparison here: COUNT(pc.ColorCode) >= (SELECT COUNT(ColorCode) FROM SelectedColors). Assuming that “hidden” key (:-p) we can use just the equal comparison like this: COUNT(pc.ColorCode) = (SELECT COUNT(ColorCode) FROM SelectedColors).
Just a tinny little tune up…
Cheers,
Leandro Nunes
@Leandro
There’s always room for improvement. :)
Thanx for your contribution.
If you use distinct in the having count then you can avoid duplicates in both tables.
SELECT Name
FROM PersonColors pc
INNER JOIN SelectedColors sc ON sc.ColorCode = pc.ColorCode
GROUP BY pc.Name
HAVING COUNT(distinct pc.ColorCode) >= (SELECT COUNT(distinct ColorCode) FROM SelectedColors)
If you insert data as mentioned below
(‘Tom’,’Red’),(‘Tom’,’Blue’), (‘Tom’,’Red’),(‘Tom’,’Blue’)
you will get Tom in output which is wrong…
@Surya,
You are correct, we will get TOM in that case.
But please read post, there is already note like:
UPDATE: Following solution is written with assumption that in SelectedColors table Name and ColorCode are Primary Key. This requirement was not specified in original question.
Thanks,
Tejas