我的 SQL Server 数据库中有两个表,我需要以相同的方式获取两个表的结果。我们有一个名为 tblEmail 的表和另一个名为 tblReply 的表。一切都从 tblEmail 表开始,每次我们的应用程序发送电子邮件时,我们都会在那里注册,当我们有外部回复时,它将在 tblReply 上。这样,tblEmail 将发送主电子邮件以及来自我的应用程序的所有回复。
还有另一个名为 tblOutgoing 的表,用于定义作为回复并链接到我们正在回复的外部回复的电子邮件。 (更改表结构不是一个选项)。
tbl电子邮件
邮箱ID | 主题 |
---|---|
1 | 发送的第一封电子邮件 |
2 | 从我的应用程序发送的第一个回复 |
3 | 从我的应用程序发送的第二个回复 |
4 | 从我的应用程序发送的第三条回复 |
tbl回复
电子邮件回复ID | 邮箱ID | 主题 |
---|---|---|
1 | 1 | 第一个外部回复 |
2 | 2 | 第二次外部回复 |
3 | 3 | 第三次外部回复 |
tbl传出
邮箱ID | 电子邮件回复ID |
---|---|
2 | 1 |
3 | 2 |
4 | 3 |
我需要的只是所有回复,发送的原始电子邮件不得在结果中(本例中EmailID = 1是原始电子邮件)。那么,如何使用原始电子邮件 ID 或任何电子邮件回复作为参数来获取结果?
我需要的结果:
邮箱ID | 电子邮件回复ID | 主题 |
---|---|---|
空 | 1 | 第一个外部回复 |
2 | 空 | 从我的应用程序发送的第一个回复 |
空 | 2 | 第二次外部回复 |
3 | 空 | 从我的应用程序发送的第二个回复 |
空 | 3 | 第三次外部回复 |
4 | 空 | 从我的应用程序发送的第三条回复 |
您的示例数据可能无法反映所有可能的情况,但对于您提供的内容,我有两种可能的解决方案。
假设 客户回复 和 应用程序回复客户回复 之间存在(大部分)1:1 关系,您可以连接所有三个表并使用
CROSS APPLY(VALUES ...)
将结果拆分为单独的行。
SELECT V.EmailID, V.EmailReplyID, V.Subject
FROM tblReply R
LEFT JOIN tblOutgoing O ON O.EmailReplyID = R.EmailReplyID
LEFT JOIN tblEmail E ON E.EmailID = O.EmailID
CROSS APPLY (
VALUES
(1, CAST(NULL AS INT), R.EmailReplyID, R.Subject),
(2, E.EmailID, CAST(NULL AS INT), E.Subject)
) V(Ordinal, EmailID, EmailReplyID, Subject)
ORDER BY R.EmailReplyID, V.Ordinal
如果关系不是 1:1,您可能需要
DISTINCT
。
另一种方法是编写两个单独的选择并使用
UNION ALL
组合结果。对结果进行排序有点棘手。下面将在内部查询中保留 EmailId
进行排序,然后在外部选择列表中过滤掉多余的值。
SELECT
CASE WHEN U.EmailReplyID IS NULL THEN U.EmailId END AS EmailId,
U.EmailReplyID,
U.Subject
FROM (
SELECT R.EmailID, R.EmailReplyID, R.Subject
FROM tblReply R
UNION ALL
SELECT E.EmailID, CAST(NULL AS INT), E.Subject
FROM tblOutgoing O
JOIN tblEmail E ON E.EmailID = O.EmailID
) U
ORDER BY U.EmailID, U.EmailReplyID
上面使用
LEFT JOIN
来考虑客户回复尚未触发应用程序回复的可能性。
对于所提供的样本数据,两者的结果相同。
邮箱ID | 电子邮件回复ID | 主题 |
---|---|---|
空 | 1 | 第一个外部回复 |
2 | 空 | 从我的应用程序发送的第一个回复 |
空 | 2 | 第二次外部回复 |
3 | 空 | 从我的应用程序发送的第二个回复 |
空 | 3 | 第三次外部回复 |
4 | 空 | 从我的应用程序发送的第三条回复 |
如果您的表有时间戳值,则可能会首选按这些值排序。
请参阅 this db<>fiddle 进行演示。