Reputation: 276
I have an issue with sql query which to me seems pretty simple but can't get it to work properly.
So I have this table:
broadcast_media_id tells me if the data is 1 - email or 2 - phone. I need to gather both email and phone for one employee (with the same employee_id).
The query I tried is this:
SELECT DISTINCT ed.employee_id,
ed.text_value AS email,
x.text_value AS phone
FROM employee_data ed
INNER JOIN
(
SELECT employee_id,
text_value
FROM employee_data
WHERE broadcast_media_id = 2
) x ON x.employee_id = ed.employee_id
WHERE broadcast_media_id = 1
Unfortunately because of the WHERE clause I get values only if employee has an email. So the result is this:
I am missing the phone value of "A773B230-754C-423F-97C4-E331268EA3C8" just because he doesn't have an email. I want to show this row as well and the value for email to be NULL.
It seems simple to me but I can't get it figured out.
I appreciate your help.
Upvotes: 0
Views: 60
Reputation: 5745
Just use LEFT JOIN if the employee always have phone.
SELECT DISTINCT ed.employee_id,
ed.text_value AS email,
x.text_value AS phone
FROM employee_data ed
LEFT JOIN
(
SELECT employee_id,
text_value
FROM employee_data
WHERE broadcast_media_id = 2
) x ON x.employee_id = ed.employee_id
WHERE broadcast_media_id = 1
you can also avoid self join, but most probably the performance will be worse
SELECT ed.employee_id,
MIN(CASE WHEN broadcast_media_id = 1 THEN text_value END) AS phone,
MIN(CASE WHEN broadcast_media_id = 2 THEN text_value END) AS email
FROM employee_data ed
GROUP BY ed.employee_id
if employee can be without phone then you can use FULL JOIN
SELECT DISTINCT
COALESCE(ed.employee_id, x.employee_id) employee_id,
ed.text_value AS email,
x.text_value AS phone
FROM
(SELECT * FROM employee_data WHERE broadcast_media_id = 1) ed
FULL JOIN (SELECT * FROM employee_data WHERE broadcast_media_id = 2) x
ON x.employee_id = ed.employee_id;
Upvotes: 1
Reputation: 2809
i would use a double LEFT JOIN like:
SELECT ed.employee_id
,COALESCE(ed1.text_value,'') as mail
,COALESCE(ed2.text_value,'') as phone
FROM employee_data ed
LEFT JOIN employee_data ed1
ON ed.employee_id = ed1.employee_id
AND ed1.broadcast_media_id = 1
LEFT JOIN employee_data ed2
ON ed.employee_id = ed2.employee_id
AND ed2.broadcast_media_id = 2
Upvotes: 0
Reputation: 883
Try this query -- I didn't use any joins though
Select
EmpID,
Max(Case When MediaID = 1 Then TextValue End) As EmailID,
Sum(Case When MediaID = 2 Then Cast(TextValue As Int) End) As PhoneNumber
From employee_data
Group By EmpID
Order By EmpID;
Here - Cost of Sorting = 78% And Table Scan = 22%. (My instance data, it will definitely vary with your system and data though.)
If you do some indexing then it will perform better.
Upvotes: 1
Reputation: 1269973
If you want to use a join
, you can use LEFT JOIN
:
SELECT ed.employee_id, ede.text_value AS email,
edp.text_value AS phone
FROM employees e LEFT JOIN
employee_data ede
ON ede.employee_id = e.employee_id AND
ede.broadcast_media_id = 1 LEFT JOIN
employee_data edp
ON edp.employee_id = e.employee_id AND
edp.broadcast_media_id = 2
Note: This assumes that you have an employees
table -- which seems very reasonable. This is quite handy for the LEFT JOIN
. This would probably have the best performance.
If you don't have an employees
table, then use a subquery (SELECT DISTINCT employee_id FROM employee_data)
.
I would tend to do this using conditional aggregation, which should also have reasonable performance.
Upvotes: 1