[英]Join two tables multiple times on same column with a lookup table in between
[英]Join the same table (multiple times) on same column to different tables
我到处都看过,但我无法找到一种有效的方式将一个表连接到同一列上的多个表。 比方说,我有如下表格:
员工
emp_id | emp_name | gender_id | age_range_id
----------------------------------------------
101 | adam | 1 | 3
102 | ashley | 2 | 2
103 | Cody | 1 | 4
游客
visitor_id | visitor_name | gender_id | emp_id | age_range_id
---------------------------------------------------------------
501 | john | 1 | 101 | 3
502 | lily | 2 | 101 | null
503 | jeff | 1 | 102 | 2
性别
gender_id | gender_name
--------------------------
1 | male
2 | female
年龄范围
age_range_id | age_range_name
------------------------------
1 | 18-25
2 | 26-35
3 | 36-45
4 | 46-55
5 | 56-65
我想要的是:
emp_id | emp_name | emp_gender_and_age_range | visitor_name | visitor_gender_and_age_range
---------------------------------------------------------------------------------------------------
101 | adam | male 36-45 | john | male 36-45
101 | adam | male 36-45 | lily | female
102 | ashley | female 26-35 | jeff | male 26-35
103 | Cody | male 46-55 | null | null
我的代码:
SELECT e.emp_id
,e.emp_name
,g1.gender_name || ' ' || a1.age_range_name emp_gender_and_age_range
,v.visitor_name
,g2.gender_name || ' ' || a2.age_range_name emp_gender_and_age_range
FROM employee e
LEFT JOIN gender g1 ON e.gender_id = g1.gender_id
LEFT JOIN age_range a1 ON e.age_range_id = a1.age_range_id
LEFT JOIN visitor v ON e.emp_id = v.emp_id
LEFT JOIN gender g2 ON v.gender_id = g2.gender_id
LEFT JOIN age_range a2 ON v.age_range_id = a2.age_range_id
有没有一种有效的方法可以在不加入两次的情况下在员工和访客身上显示性别姓名?
我还在Select部分尝试了子查询:
SELECT e.emp_id
,e.emp_name
,(SELECT g1.gender_name || ' ' || a1.age_range_name
FROM gender g1, age_range a1
WHERE e.gender_id = g1.gender_id AND e.age_range_id = a1.age_range_id)
emp_gender_and_age_range
,g1.gender_name || ' ' || a1.age_range_name
emp_gender_and_age_range
,v.visitor_name
,(SELECT g2.gender_name || ' ' || a2.age_range_name
FROM gender g2, age_range a2
WHERE v.gender_id = g2.gender_id AND v.age_range_id = a2.age_range_id)
visitor_gender_and_age_range
FROM employee e
-- LEFT JOIN gender g1 ON e.gender_id = g1.gender_id
-- LEFT JOIN age_range a1 ON e.age_range_id = a1.age_range_id
LEFT JOIN visitor v ON e.emp_id = v.emp_id
-- LEFT JOIN gender g2 ON v.gender_id = g2.gender_id
-- LEFT JOIN age_range a2 ON v.age_range_id = a2.age_range_id
但是,上述查询的问题是, visitor_gender_and_age_range为Lily返回null
emp_id | emp_name | emp_gender_and_age_range | visitor_name | visitor_gender_and_age_range
---------------------------------------------------------------------------------------------------
101 | adam | male 36-45 | john | male 36-45
101 | adam | male 36-45 | lily | **NULL**
102 | ashley | female 26-35 | jeff | male 26-35
103 | Cody | male 46-55 | null | null
注意:我没有特别测试上面的查询。 但是,我的表与上面的示例完全相似。
谢谢你。
否。在这两种情况下(员工和访客),性别和年龄范围都是查找代码。 这些代码中的每一个都必须分别在 gender 和 age_range 表中查找。
每个查找都需要自己的连接,因为每个查找都可能返回不同的行。
不,你不能,但你可以使用SQL 标量宏来使其更短/更容易阅读,以防 Oracle 21+。
SQL 标量宏示例: DBFiddle 上的完整示例
create or replace function get_gender_age(p_gender_id int, p_age_range_id int)
return varchar2 sql_macro(scalar)
is
begin
return q'[(
(SELECT gender_name from gender where gender_id = p_gender_id)
||' '||
(SELECT age_range_name from age_range where age_range_id = p_age_range_id)
)]';
end;
/
并查询:
SELECT e.emp_id
,e.emp_name
,get_gender_age(e.gender_id,e.age_range_id) as emp_gender_and_age_range
,v.visitor_name
,get_gender_age(v.gender_id,v.age_range_id) as vis_gender_and_age_range
FROM employee e
LEFT JOIN visitor v ON e.emp_id = v.emp_id
(您也可以使用内联 PL/SQL 函数,但我不建议这样做,因为在这种情况下性能较低)
或者您可以使用 CTE:
with gender_age as (
SELECT
g.gender_id
,a.age_range_id
,g.gender_name || ' ' || a1.age_range_name as gender_and_age_range
FROM gender g, age_range a
)
SELECT e.emp_id
,e.emp_name
,g1.gender_and_age_range as emp_gender_and_age_range
,v.visitor_name
,g2.gender_and_age_range as vis_gender_and_age_range
FROM
employee e
LEFT JOIN gender_age g1 USING(gender_id, age_range_id)
LEFT JOIN visitor v ON e.emp_id = v.emp_id
LEFT JOIN gender_age g2 USING(gender_id, age_range_id)
但是不管怎么说,还是2次查找。
有没有一种有效的方法可以在不加入两次的情况下在员工和访客身上显示性别姓名?
根据关系代数,连接两次是连接这些关系的标准方法。
此外,您还需要考虑,如果索引gender (gender_id)
可用,加入两次会非常有效。 我不会花时间解决这两个连接问题。
我看不到你对此的担忧。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.