Sql 需要帮助在Oracle中创建正确的联接吗

Sql 需要帮助在Oracle中创建正确的联接吗,sql,oracle,join,Sql,Oracle,Join,我是一名前端开发人员,负责创建一个查询,为数据库中存储的符合特定条件的用户提取联系人数据(电子邮件)。有些用户没有电子邮件地址,但我希望他们的其他信息无论如何都能显示出来。我读过关于Oracle连接的文章,但似乎没有理解。下面是添加联接之前的代码 SELECT p.person_id, p.first_name || ' ' || p.last_name person_name, pci.contact_data FROM cse.meeting m, cse.person p, cse.me

我是一名前端开发人员,负责创建一个查询,为数据库中存储的符合特定条件的用户提取联系人数据(电子邮件)。有些用户没有电子邮件地址,但我希望他们的其他信息无论如何都能显示出来。我读过关于Oracle连接的文章,但似乎没有理解。下面是添加联接之前的代码

SELECT p.person_id, p.first_name || ' ' || p.last_name person_name, pci.contact_data
 FROM cse.meeting m, cse.person p, cse.meeting_person mp, cse.person_contact_info pci
WHERE mp.meeting_id = m.meeting_id
  AND mp.person_id = p.person_id
  AND mp.person_id = pci.person_id
  AND m.meeting_date >= '03-Jan-2020'
  AND pci.contact_type_code = 'EMAIL'
ORDER BY m.session_date ASC;
我试过这两种方法:

AND mp.person_id = pci.person_id(+)

没有成功。我还尝试使用显式代码来实现它:

SELECT p.person_id, p.first_name || ' ' || p.last_name person_name, pci.contact_data
 FROM cse.meeting m, cse.person p, cse.meeting_person mp LEFT JOIN cse.person_contact_info pci ON mp.person_id = pci.person_id
WHERE mp.meeting_id = m.meeting_id
  AND mp.person_id = p.person_id
  AND m.meeting_date >= '03-Jan-2020'
  AND pci.contact_type_code = 'EMAIL'
ORDER BY m.session_date ASC;
还是不走运。它不会返回表person\u contact\u info中没有联系人类型代码为“EMAIL”的行的人的数据。有人能告诉我我做错了什么吗?“加入”的概念有点让我难以理解


谢谢

我想我明白了问题所在。如果别名为
pci
cse.person\u contact\u info
中不存在该记录,则字段
pci.contact\u type\u code
NULL
。这是因为如果未在联接表中找到,
左联接
将用
NULL
填充字段

因此,当您在
WHERE
子句中调用
pci.contact\u type\u code='EMAIL'
时,它与未找到的记录不匹配,因为该字段在
JOIN
中填充了
NULL


为此,请将where子句中的这一行:
和pci.contact\u-type\u-code='EMAIL'
更改为
和(pci.contact\u-type\u-code='EMAIL'或pci.contact\u-type\u-code为空)。
这将接受所有
pci.contact\u-type\u-code
或未找到电子邮件的情况(
NULL
).

我想我看到了问题所在。如果别名为
pci
cse.person\u contact\u info
中不存在该记录,则字段
pci.contact\u type\u code
NULL
。这是因为如果未在联接表中找到,
左联接
将用
NULL
填充字段

因此,当您在
WHERE
子句中调用
pci.contact\u type\u code='EMAIL'
时,它与未找到的记录不匹配,因为该字段在
JOIN
中填充了
NULL


为此,请将where子句中的这一行:
和pci.contact\u-type\u-code='EMAIL'
更改为
和(pci.contact\u-type\u-code='EMAIL'或pci.contact\u-type\u-code为空)。
这将接受所有
pci.contact\u-type\u-code
或未找到电子邮件的情况(
NULL
)。将所有外部联接的条件放在其
on
子句中,即使该条件似乎不太属于那里:

LEFT JOIN cse.person_contact_info pci ON mp.person_id = pci.person_id
AND pci.contact_type_code = 'EMAIL'
因此,还要替换旧样式的连接以保持一致:

SELECT p.person_id, p.first_name || ' ' || p.last_name person_name, pci.contact_data
FROM cse.meeting m
JOIN cse.meeting_person mp ON mp.meeting_id = m.meeting_id
JOIN cse.person p ON p.person_id = mp.person_id
LEFT JOIN cse.person_contact_info pci ON pci.person_id = p.person_id
AND pci.contact_type_code = 'EMAIL'
WHERE m.meeting_date >= DATE '2020-01-03'
ORDER BY m.session_date ASC;
使用单一样式不仅仅是为了一致性;首先计算新样式的联接,因此,对于混合引用的更复杂查询,可能会出现奇怪的错误

我还使用了目标日期;您正在与字符串进行比较,该字符串依赖于隐式转换,如果运行该字符串的人对您具有不同的NLS设置,则将失败


旧样式外部联接的问题是相同的,只是看起来不同。您有对
pci
的外部和内部引用:

AND mp.person_id = pci.person_id(+)
AND pci.contact_type_code = 'EMAIL'
因此,如果您必须以这种方式执行此操作,则需要将两个部分都设置为外部(并可能通过交换术语使其更易于遵循):


除非你有很好的理由,否则无论如何你都应该使用新样式的连接New在这里的意思是1992年,所以当然不是真正的New。

您有一个外部连接条件,但随后您也参考了
where
子句中的
pci
表,其效果是将其转回到内部连接。将所有外部联接的条件放在其
on
子句中,即使该条件似乎不太属于那里:

LEFT JOIN cse.person_contact_info pci ON mp.person_id = pci.person_id
AND pci.contact_type_code = 'EMAIL'
因此,还要替换旧样式的连接以保持一致:

SELECT p.person_id, p.first_name || ' ' || p.last_name person_name, pci.contact_data
FROM cse.meeting m
JOIN cse.meeting_person mp ON mp.meeting_id = m.meeting_id
JOIN cse.person p ON p.person_id = mp.person_id
LEFT JOIN cse.person_contact_info pci ON pci.person_id = p.person_id
AND pci.contact_type_code = 'EMAIL'
WHERE m.meeting_date >= DATE '2020-01-03'
ORDER BY m.session_date ASC;
使用单一样式不仅仅是为了一致性;首先计算新样式的联接,因此,对于混合引用的更复杂查询,可能会出现奇怪的错误

我还使用了目标日期;您正在与字符串进行比较,该字符串依赖于隐式转换,如果运行该字符串的人对您具有不同的NLS设置,则将失败


旧样式外部联接的问题是相同的,只是看起来不同。您有对
pci
的外部和内部引用:

AND mp.person_id = pci.person_id(+)
AND pci.contact_type_code = 'EMAIL'
因此,如果您必须以这种方式执行此操作,则需要将两个部分都设置为外部(并可能通过交换术语使其更易于遵循):


除非你有很好的理由,否则无论如何你都应该使用新样式的连接这里的“新”是指1992年,所以当然不是真正的“新”。

您希望显示所有分配到2020年1月3日至少一次会议的人员。因此,请从表
person
中选择

您可以在
WHERE
子句中使用
IN
EXISTS
子句来指定条件,但您希望按会议的会话日期排序,因此必须加入会议表。(这有点奇怪,因为当您按会话日期排序时,没有显示它,从而使查询结果看起来无序。)

然后,如果此人有电子邮件,您希望显示电子邮件。因此,请加入表
person\u contact\u info

以下是查询:

SELECT
  p.person_id, 
  p.first_name || ' ' || p.last_name AS person_name,
  pci.contact_data
 FROM cse.person p
 JOIN cse.meeting_person mp ON mp.person_id = p.person_id
 JOIN cse.meeting m ON m.meeting_id = mp.meeting_id
                   AND m.meeting_date >= DATE '2020-01-03'
 LEFT JOIN cse.person_contact_info pci ON pci.person_id = p.person_id
                                      AND pci.contact_type_code = 'EMAIL'
ORDER BY m.session_date;

(还有一件事:您将在2020年1月3日加入一个人的会议。如果一个人当天有三次会议,您将向该人显示三次。因此,您可能确实希望在
中使用
,或者改为使用
EXISTS

您希望显示在2020年1月3日至少分配了一次会议的所有人。因此,请从表
person
中选择

你会