sql – 防止LEFT JOIN中的重复值

我遇到了从LEFT JOIN获得重复值的情况.我认为这可能是一种理想的行为,但与我想要的不同.

我有三张桌子:人,部门和联系人.

人:

id bigint,person_name character varying(255)

部 :

person_id bigint,department_name character varying(255)

联系 :

person_id bigint,phone_number character varying(255)

SQL查询

SELECT p.id,p.person_name,d.department_name,c.phone_number 
FROM person p
  LEFT JOIN department d 
    ON p.id = d.person_id
  LEFT JOIN contact c 
    ON p.id = c.person_id;

结果:

id|person_name|department_name|phone_number
--+-----------+---------------+------------
1 |"John"     |"Finance"      |"023451"
1 |"John"     |"Finance"      |"99478"
1 |"John"     |"Finance"      |"67890"
1 |"John"     |"Marketing"    |"023451"
1 |"John"     |"Marketing"    |"99478"
1 |"John"     |"Marketing"    |"67890"
2 |"Barbara"  |"Finance"      |""
3 |"Michelle" |""             |"005634"

我知道这是联接做的事情,保持与所选行相乘.但是它给出了两个部门的电话号码023451,99478,67890的意义,而它们只与人约翰有关,不必要的重复值会使更大的数据集升级问题.
所以,这就是我想要的:

id|person_name|department_name|phone_number
--+-----------+---------------+------------
1 |"John"     |"Finance"      |"023451"
1 |"John"     |"Marketing"    |"99478"
1 |"John"     |""             |"67890"
2 |"Barbara"  |"Finance"      |""
3 |"Michelle" |""             |"005634"

这是我的情况的一个示例,我正在使用大量的表和查询.所以,需要一种通用的解决方案.

解决方法

我喜欢称这个问题为“通过代理交叉加入”.由于没有信息(WHERE或JOIN条件)表部门和联系人应该如何匹配,他们通过代理表人交叉加入 – 给你 Cartesian product.非常类似于这个:

> Two SQL LEFT JOINS produce incorrect result

那里有更多解释.

您的查询解决方案:

SELECT p.id,c.phone_number
FROM   person p
LEFT   JOIN (
  SELECT person_id,min(department_name) AS department_name
  FROM   department
  GROUP  BY person_id
  ) d ON d.person_id = p.id
LEFT   JOIN (
  SELECT person_id,min(phone_number) AS phone_number
  FROM   contact
  GROUP  BY person_id
  ) c ON c.person_id = p.id;

您没有定义要选择的部门或电话号码,因此我随意选择了第一个部门或电话号码.你可以用任何其他方式……

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...