SQL 在 table 行之间加入
SQL join between table rows
我的 sql 查询有问题,对我来说这看起来很简单,但无法正常工作。
所以我有这个 table:
broadcast_media_id 告诉我数据是 1 - 电子邮件还是 2 - phone。我需要为一名员工收集电子邮件和 phone(具有相同的 employee_id)。
我试过的查询是这样的:
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
不幸的是,由于 WHERE 子句,我仅在员工有电子邮件时才获取值。所以结果是这样的:
我错过了 "A773B230-754C-423F-97C4-E331268EA3C8" 的 phone 值,只是因为他没有电子邮件。我也想显示这一行,并且电子邮件的值为 NULL。
我觉得很简单,但我想不通。
感谢您的帮助。
如果员工总是 phone,只需使用 LEFT JOIN。
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
你也可以避免自连接,但很可能性能会更差
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
如果员工可以没有 phone 那么你可以使用 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;
如果你想使用join
,你可以使用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
注意:这假设您有一个 employees
table -- 这看起来很合理。这对于 LEFT JOIN
来说非常方便。这可能会有最好的性能。
如果您没有 employees
table,则使用子查询 (SELECT DISTINCT employee_id FROM employee_data)
。
我倾向于使用条件聚合来执行此操作,它也应该具有合理的性能。
试试这个查询——虽然我没有使用任何连接
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;
此处 - 分拣成本 = 78%,Table 扫描成本 = 22%。
(我的实例数据,它肯定会因您的系统和数据而异。)
如果你做一些索引,那么它会表现得更好。
我会使用双 LEFT JOIN,例如:
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
我的 sql 查询有问题,对我来说这看起来很简单,但无法正常工作。
所以我有这个 table:
我试过的查询是这样的:
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
不幸的是,由于 WHERE 子句,我仅在员工有电子邮件时才获取值。所以结果是这样的:
我错过了 "A773B230-754C-423F-97C4-E331268EA3C8" 的 phone 值,只是因为他没有电子邮件。我也想显示这一行,并且电子邮件的值为 NULL。
我觉得很简单,但我想不通。
感谢您的帮助。
如果员工总是 phone,只需使用 LEFT JOIN。
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
你也可以避免自连接,但很可能性能会更差
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
如果员工可以没有 phone 那么你可以使用 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;
如果你想使用join
,你可以使用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
注意:这假设您有一个 employees
table -- 这看起来很合理。这对于 LEFT JOIN
来说非常方便。这可能会有最好的性能。
如果您没有 employees
table,则使用子查询 (SELECT DISTINCT employee_id FROM employee_data)
。
我倾向于使用条件聚合来执行此操作,它也应该具有合理的性能。
试试这个查询——虽然我没有使用任何连接
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;
此处 - 分拣成本 = 78%,Table 扫描成本 = 22%。 (我的实例数据,它肯定会因您的系统和数据而异。)
如果你做一些索引,那么它会表现得更好。
我会使用双 LEFT JOIN,例如:
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