加入两个没有唯一键的表

时间:2016-12-08 17:04:15

标签: sql sql-server tsql

我有一个导入数据并发送电子邮件的程序。我有另一个存储smtp电子邮件日志信息的进程。

我使用电子邮件日志进行报告,以便为用户提供信息,例如:弹跳,交付等...

我遇到的问题是用户想要帐号,该帐号存储在另一个电子邮件信息表中,即不是smtp电子邮件日志。

我目前唯一可以将两张桌子绑在一起的方法是通过电子邮件地址和日期。大多数情况下,这足以找到正确的帐号。

问题在于,同一天可能有3封来自不同帐户的电子邮件具有相同的电子邮件地址,例如

Account number Email Address     Date 
----------------------------------------------
1              email@address.com 9/12/2016 
2              email@address.com 9/12/2016 
3              email@address.com 9/12/2016

当我按如下方式加入两个表时: -

select l.event, l.[time], l.SendTime, l.Recipient, e.AccountNumber from emaillog l 
OUTER APPLY 
(SELECT TOP 1 AccountNumber from emailData e 
where e.EmailAddress = l.Recipient and Convert(date, [DateEmailed]) = Convert(date, l.Time) 
) as e 
where Convert(date, l.Time) = '2016-12-09';

我得到了

Account number Email Address     Date 
--------------------------------------------- 
1              email@address.com 9/12/2016 
1              email@address.com 9/12/2016 
1              email@address.com 9/12/2016

即。它总是在我的电子邮件表中找到第一条记录,因为电子邮件地址和日期匹配。

我有什么方法可以获得正确的帐号吗?

我确实考虑过编写一个从电子邮件日志创建临时表的SP,找到多个条目,然后在电子邮件数据表的第1行的帐号中输入日志行1。

我只是想知道我是否错过了一两个SQL技巧!

2 个答案:

答案 0 :(得分:0)

有一些语法问题,所以我会发布更正的代码但是,谢谢你指出我正确的方向。我对SQL服务器很生疏。

   select l.event, l.[time], l.SendTime, l.Recipient, ed.AccountNumber
from (select l.*,
             row_number() over (partition by recipient, Convert(date, [time]) order by [time]) as seqnum
      from emaillog as l 
     ) as l left join
     (select ed.*,
             row_number() over (partition by emailaddress, Convert(date, [DateEmailed])  order by [DateEmailed]) as seqnum
      from ebilldata as ed
     ) as ed
     on ed.EmailAddress = l.Recipient and ed.seqnum = l.seqnum
where Convert(date, l.Time) = '2016-12-06';   

答案 1 :(得分:-1)

相反,列举电子邮件和回复,建议:

select l.event, l.[time], l.SendTime, l.Recipient, ed.AccountNumber
from (select l.*,
             row_number() over (partition by recipient, Convert(date, [DateEmailed] order by dateemailed) as seqnum
      from emaillog as l 
     ) as l left join
     (select ed.*
             row_number() over (partition by recipient, Convert(date, [time] order by time) as seqnum
      from emaildata as ed
     ) as ed
     on ed.EmailAddress = l.Recipient and ed.seqnum = l.seqnum
where Convert(date, l.Time) = '2016-12-09';