当没有ID时,SQL从记录值中减去前一行

时间:2014-03-14 20:11:59

标签: sql

我遇到的问题类似于此处发布的问题" How can I subtract a previous row in sql?" 但更复杂。有些解决方案使用递增的ID号,我的数据本身并不具备此功能,但如果需要,可以打开添加一个(但需要查询帮助才能执行此操作)。 我试图找到EACH用户打开电子邮件之间的平均天数。 我的数据看起来像这样

**Email Address | Open Date |  CampaignName**

Email1@gmail     |  01/01/2013 | WelcomeCampaign
Email1@gmail     |  03/01/2013 | WelcomeCampaign
Email1@gmail     |  05/20/2013 | WelcomeCampaign
Email2@gmail     |  01/16/2013 | WelcomeCampaign
Email2@gmail     |  02/28/2013 | WelcomeCampaign
Email3@gmail     |  01/05/2013 | WelcomeCampaign
Email3@gmail     |  01/10/2013 | WelcomeCampaign
Email3@gmail     |  02/15/2013 | WelcomeCampaign
Email3@gmail     |  03/15/2013 | WelcomeCampaign
Email3@gmail     |  04/02/2013 | WelcomeCampaign

需要获取这样的数据,如果电子邮件地址匹配,则从前一记录中减去每个日期

**Email Address | Open Date |  CampaignName | DaysBetween**

Email1@gmail     |  01/01/2013 | WelcomeCampaign | NA
Email1@gmail     |  03/01/2013 | WelcomeCampaign | 60
Email1@gmail     |  05/20/2013 | WelcomeCampaign | 80
Email2@gmail     |  01/16/2013 | WelcomeCampaign | NA
Email2@gmail     |  02/28/2013 | WelcomeCampaign | 42
Email3@gmail     |  01/05/2013 | WelcomeCampaign | NA
Email3@gmail     |  01/10/2013 | WelcomeCampaign | 5
Email3@gmail     |  02/15/2013 | WelcomeCampaign | 35
Email3@gmail     |  03/15/2013 | WelcomeCampaign | 30
Email3@gmail     |  04/02/2013 | WelcomeCampaign | 17

然后我计划为每个用户平均(email2 @gmail将是70天)

2 个答案:

答案 0 :(得分:0)

执行此操作的方法因数据库而异,您尚未指定,但如果LAG()可用,则非常简单:

SELECT *,DATEDIFF(day,OpenDate,LAG(OpenDate) OVER(PARTITION BY EmailAddress ORDER BY OpenDate)) As DaysBetween
FROM Table1

如果它不可用,你将进行偏移自连接以实现相同目的:

WITH cte AS (SELECT *,ROW_NUMBER() OVER(PARTITION BY EmailAddress ORDER BY OpenDate) AS RN
             FROM Table1)
SELECT a.*,DATEDIFF(day,a.OpenDate,b.OpenDate) AS DaysBetween
FROM cte a
LEFT JOIN cte b
  ON a.EmailAddress = b.EmailAddress
  AND a.RN = b.RN+1

两者的演示:SQL Fiddle

上面的一个将在大多数dbms(当然是语法差异)中起作用,但在MySQL中不起作用。

答案 1 :(得分:0)

如果您想获得电子邮件之间的平均天数,可以采用更简单的方式。

select EmailAddress, 
       (case when count(*) > 1 then (max(OpenDate) - Min(OpenDate)) / (count(*) - 1)
        end) as AvgTimeBetweenEmails
from table t
group by EmailAddress;

平均持续时间是最长开放日期减去最低开放日期除以电子邮件数减去1。

至于你的问题的答案,你想使用lag()函数,如果你的数据库支持它。