如何查询具有相同字段的两个表,仅当字段值相同时才返回id
Posted
技术标签:
【中文标题】如何查询具有相同字段的两个表,仅当字段值相同时才返回id【英文标题】:How to query two tables that have the same field, that returns id only if field value is the same 【发布时间】:2020-09-19 15:47:54 【问题描述】:我有两个表格(电子邮件和电话)指示是否打开了消息(阅读/收听)。我需要找到尚未打开消息的成员的 ID(他们可能已收到电子邮件并致电)。因此,他们没有收到消息的唯一情况是他们没有打开电子邮件或接听电话。
我有一个看起来像这样的查询,以了解他们是否打开了它:
SELECT person_id, last_name, first_name
FROM person
WHERE person_id IN (
SELECT DISTINCT person_id
FROM (
SELECT person_id
FROM msg_email WHERE message_id = ? AND opened = 'Y'
UNION ALL
SELECT person_id
FROM msg_voice WHERE message_id = ? AND opened = 'Y') tt
)
ORDER BY last_name ASC, first_name ASC"
但是,这仅适用于了解它是否通过任何一种交付方式打开。
我将如何设计一个查询来查找收到消息的人员的 ID(存在是两个表之一),但打开的值在两个表中都是“N”?
样本数据 人表
person_id firstname lastname
1 Joe Smith
2 Tom Jones
msg_email 表
message_id person_id opened
1 1 N
1 2 Y
msg_phone 表
message_id person_id opened
1 1 N
1 2 N
所以我需要一个只返回 Joe Smith 的查询
【问题讨论】:
样本数据对您的问题有很大帮助。 样本数据和期望的结果会有所帮助。 如果您想要“未打开消息的成员的ID”,为什么要在代码中使用条件...AND opened = 'Y'
?
按要求添加样本数据
【参考方案1】:
嗯,一个方法是一系列EXISTS
/IN
条件:
SELECT p.person_id, p.last_name, p.first_name
FROM person p
WHERE EXISTS (SELECT 1
FROM msg_email e
WHERE e.person_id = p.person_id AND e.opened = 'N'
) AND
NOT EXISTS (SELECT 1
FROM msg_email e
WHERE e.person_id = p.person_id AND e.opened = 'Y'
) AND
EXISTS (SELECT 1
FROM msg_voice v
WHERE v.person_id = p.person_id AND v.opened = 'N'
) AND
NOT EXISTS (SELECT 1
FROM msg_voice v
WHERE v.person_id = p.person_id AND v.opened = 'Y'
)
ORDER BY last_name ASC, first_name ASC;
我推荐EXISTS
而不是IN
,因为它通常具有更好的性能。如果您在 msg_email(person_id, opened)
和 msg_voice(person_id, opened)
上有索引,那将是正确的。
编辑:
我突然想到,您希望在任一表中都出现'N'
,而在两个表中都没有'Y'
。逻辑类似,但是:
SELECT p.person_id, p.last_name, p.first_name
FROM person p
WHERE (EXISTS (SELECT 1
FROM msg_email e
WHERE e.person_id = p.person_id AND e.opened = 'N'
) OR
EXISTS (SELECT 1
FROM msg_voice v
WHERE v.person_id = p.person_id AND v.opened = 'N'
)
) AND
NOT EXISTS (SELECT 1
FROM msg_email e
WHERE e.person_id = p.person_id AND e.opened = 'Y'
) AND
NOT EXISTS (SELECT 1
FROM msg_voice v
WHERE v.person_id = p.person_id AND v.opened = 'Y'
)
ORDER BY last_name ASC, first_name ASC;
【讨论】:
戈登,非常感谢!你的最后一次更新正是我所需要的。当然是我需要提出的更具挑战性的查询之一。 Gordon,该解决方案确实需要一组括号将存在条件与不存在条件分开。以上是关于如何查询具有相同字段的两个表,仅当字段值相同时才返回id的主要内容,如果未能解决你的问题,请参考以下文章