我有两个表(电子邮件和电话),用于指示是否打开了一条消息(已读/已听)。我需要找到尚未打开消息的成员的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
所以我需要一个只返回乔·史密斯的查询
答案 0 :(得分: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;