I have a bit of SQL that is almost doing what I want it to do. I'm working with three tables, a Users, UserPhoneNumbers and UserPhoneNumberTypes. I'm trying to get a list of users with their phone numbers for an export.
The database itself is old and has some integrity issues. My issue is that there should only ever be 1 type of each phone number in the database but thats not the case. When I run this I get multi-line results for each person if they contain, for example, two "Home" numbers.
How can I modify the SQL to take the first phone number listed and ignore the remaining numbers? I'm in SQL Server and I know about the TOP statement. But if I add 'TOP 1' to the LEFT JOIN select statement its just giving me the 1st entry in the database, not the 1st entry for each User.
This is for SQL Server 2000.
Thanks,
SELECT Users.UserID,
Users.FirstName, Users.LastName,
HomePhone, WorkPhone, FaxNumber
FROM Users
LEFT JOIN
(SELECT UserID, PhoneNumber AS HomePhone
FROM UserPhoneNumbers LEFT JOIN UserPhoneNumberTypes ON UserPhoneNumbers.UserPhoneNumberTypeID=UserPhoneNumberTypes.UserPhoneNumberTypeID
WHERE UserPhoneNumberTypes.PhoneNumberType='Home') AS tmpHomePhone
ON tmpHomePhone.UserID = Users.UserID
LEFT JOIN
(SELECT UserID, PhoneNumber AS WorkPhone
FROM UserPhoneNumbers LEFT JOIN UserPhoneNumberTypes ON UserPhoneNumbers.UserPhoneNumberTypeID=UserPhoneNumberTypes.UserPhoneNumberTypeID
WHERE UserPhoneNumberTypes.PhoneNumberType='Work') AS tmpWorkPhone
ON tmpWorkPhone.UserID = Users.UserID
LEFT JOIN
(SELECT UserID, PhoneNumber AS FaxNumber
FROM UserPhoneNumbers LEFT JOIN UserPhoneNumberTypes ON UserPhoneNumbers.UserPhoneNumberTypeID=UserPhoneNumberTypes.UserPhoneNumberTypeID
WHERE UserPhoneNumberTypes.PhoneNumberType='Fax') AS tmpFaxNumber
ON tmpFaxNumber.UserID = Users.UserID
Assuming SQL Server 2005+, use ROW_NUMBER:
Mind the
what?
placeholder for determining the first number. Omit the ORDER BY if you don't care at all...You could just use GROUP BY:
Instead of min(), you could use max() as well.
Or you could do it in one group by:
Hold on, just to understand the question.
You've got two tables:
First off there's no need for temp tables:
Add inner joins as necessary.
Or am I missing something?
Whenever you want to select only a top row from a left table for each row in the right table you should consider using the APPLY operator instead of join, and move the join condition inside the left join:
In this solution, for each user and phone number type, I'm picking the lowest primary key value from the
UserPhoneNumbers
table (I guessed that the column was namedUserPhoneNumberId
).You have to define what you mean by "first" when there are two numbers of the same type, and then add a condition to your join so that only the correct record meets the criteria. There's no other shortcut for this.