选择两行为一

时间:2019-10-11 16:17:44

标签: sql sql-server

我正在从交易表中生成有关最新电子邮件更改的报告,而我目前正在得到如下结果:

+------------+--------+------+------------+--------------+--------------+------------+
|    Date    |  Time  | Acct |    Name    |   EmailOld   |   EmailNew   | ChangeType |
+------------+--------+------+------------+--------------+--------------+------------+
| 2019-10-11 | 8:05AM | 1234 | John Smith |              | John@new.com | INSERT     |
| 2019-10-11 | 8:04AM | 1234 | John Smith | John@old.com |              | DELETE     |
+------------+--------+------+------------+--------------+--------------+------------+

我想合并为一个这样的结果:

+------------+--------+------+------------+--------------+--------------+------------+
|    Date    |  Time  | Acct |    Name    |   EmailOld   |   EmailNew   | ChangeType |
+------------+--------+------+------------+--------------+--------------+------------+
| 2019-10-11 | 8:05AM | 1234 | John Smith | John@old.com | John@new.com | UPDATE     |
+------------+--------+------+------------+--------------+--------------+------------+

我尝试围绕此构建: Two Rows into one row in SQL

Format Two Rows into One Row

但是它们正在处理数字值,因此不适用于我的情况。

到目前为止,这是我从数据库中提取SQL时的样子:

SELECT Date, Time, Acct, Name, EmailOld, EmailNew,
CASE
WHEN EmailOld = '' AND EmailNew <> '' THEN 'INSERT'
WHEN EmailOld <> '' AND EmailNew = '' THEN 'DELETE'
ELSE 'UPDATE'
END AS ChangeType,
ROW_NUMBER() OVER(PARTITION BY Acct ORDER BY Date, Time) AS RowNum
FROM EmailChanges

3 个答案:

答案 0 :(得分:0)

您可以尝试

with ins as (
select * from YourTable where ChangeType = 'INSERT'
)
, del as (
select * from YourTable where ChangeType = 'DELETE'
)
select Date, Time, Acct, Name
, EmailOld = iif(ins.EmailOld = '', del.EmailOld, ins.EmailOld)
, EmailNew = iif(ins.EmailNew = '', del.EmailNew, ins.EmailNew)
, ChangeType = 'UPDATE'
from ins 
    inner join del on del.Acct = ins.Acct

答案 1 :(得分:0)

这里的问题是如何在EmailChanges表中记录事物。对于这些记录,我认为事务是按以下方式实现的:

  • 电子邮件已删除,行已更新
  • 已添加新电子邮件,行已更新。

现在我必须在这里做出一些假设才能理解这一点。我必须假设电子邮件存储在单独的表中,每封电子邮件仅一行,并且出于历史目的,您在更改电子邮件地址时将旧电子邮件地址标记为已删除(而不是实际删除电子邮件记录),然后立即添加新的电子邮件地址。这是一个很好的模式,可让您跟踪客户的电子邮件地址和地址更改。

但是,如果记录是通过触发器完成的,则这是发生的模式,因为已经运行了两个单独的操作。 (如果此日志记录是通过编程方式完成的,则更改程序日志更新的方式。)

正如我所说,我正在做假设,但它们是针对上述情况的合理假设。要使它们成为UPDATE,您有几种不同的方法,除了一种方法,没有一种方法可以正确捕获更新。我将使用的方法是在对电子邮件地址的UPDATE上创建INSTEAD OF触发器。在一个事务中,这会将旧电子邮件地址标记为DELETED,添加新的电子邮件地址记录,并将UPDATE事务记录到表中。然后,您的代码将执行一个操作(UPDATE),而不是执行两个单独的调用来更新电子邮件地址(UPDATE ... SET Deleted,INSERT),然后由INSTEAD OF触发器处理详细信息。

答案 2 :(得分:0)

检查此-

SELECT [Date],[Time],Acct, [Name],EmailOld,EmailNew,
CASE
WHEN EmailOld <> '' AND EmailNew <> '' AND EmailOld<>EmailNew THEN 'UPDATE'
WHEN EmailOld = '' AND EmailNew <> '' THEN 'INSERT'
WHEN EmailOld <> '' AND EmailNew = '' THEN 'DELETE'
END AS ChangeType FROM 
(
SELECT [Date], MAX([Time]) AS [Time], Acct, [Name],
LTRIM(RTRIM(STRING_AGG(EmailOld,''))) AS EmailOld,LTRIM(RTRIM(STRING_AGG(EmailNew,''))) AS EmailNew
FROM EmailChanges
GROUP BY [Date],Acct,[Name]
) T;