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
WITH myquery AS ( SELECT * FROM TEST_FILE1 ) , a as ( select col1, col2, 42 as col3, col4, col5 from ( (select distinct col1 from myquery) cross join (select distinct col2 from myquery) cross join (select distinct col4 from myquery) cross join (select distinct col5 from myquery) ) ) select a.
This LIMIT clause would return 3 records in the result set with an offset of 1. What this means is that the SELECT statement would skip the first record that would normally be returned and instead return the second, third, and fourth records.
1 Answer. The order doesn't matter for INNER joins. As long as you change your selects from SELECT * to SELECT a.
The SQL LEFT JOIN returns all rows from the left table, even if there are no matches in the right table. This means that if the ON clause matches 0 (zero) records in the right table; the join will still return a row in the result, but with NULL in each column from the right table.
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:
SELECT u.UserID, u.FirstName, u.LastName, hn.PhoneNumber AS HomePhone FROM Users u OUTER APPLY ( SELECT TOP(1) PhoneNumber FROM UserPhoneNumbers upn LEFT JOIN UserPhoneNumberTypes upt ON upn.UserPhoneNumberTypeID=upt.UserPhoneNumberTypeID WHERE upt.PhoneNumberType='Home' AND upn.UserID = u.UserID ORDER BY ...) as hn ...
Assuming SQL Server 2005+, use ROW_NUMBER:
LEFT JOIN (SELECT UserID, PhoneNumber AS HomePhone, ROW_NUMBER() OVER (PARTITION BY userid ORDER BY what?) AS rank FROM UserPhoneNumbers upn LEFT JOIN UserPhoneNumberTypes upnt ON upnt.UserPhoneNumberTypeID = upn.UserPhoneNumberTypeID AND upnt.PhoneNumberType='Home') AS tmpHomePhone ON tmpHomePhone.UserID = Users.UserID AND tmpHomePhone.rank = 1
Mind the what?
placeholder for determining the first number. Omit the ORDER BY if you don't care at all...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With