简体   繁体   English

当不存在ID时,SQL从记录值中减去上一行

[英]SQL subtract previous row from record value when no ID exists

I have a problem that is similar to the question posted here " How can I subtract a previous row in sql? " but is more complex. 我有一个与此处发布的问题类似的问题“ 如何在sql中减去上一行? ”但更为复杂。 Some solutions use an incremented ID number, my data does not natively have this, but open adding one if needed (but would need help with query to do this). 某些解决方案使用递增的ID号,我的数据本身没有此编号,但需要时打开添加一个(但需要查询帮助来做到这一点)。 I am trying to find the average number of days between email-opens for EACH user. 我正在尝试查找每个EACH用户打开电子邮件的平均天数。 my data looks like this 我的数据看起来像这样

**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

The need is to get the data like this, where each date is subtracted from the previous record if email address matches 需要获取这样的数据,如果电子邮件地址匹配,则从上一个记录中减去每个日期

**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

I then plan to average for each user (email2@gmail would be 70 days) 然后,我计划平均每个用户(email2 @ gmail为70天)

The method to do this varies by database, which you haven't specified, but if LAG() is available, this is very easy: 这样做的方法因数据库(未指定)而异,但是如果LAG()可用,这很容易:

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

If it's not available you'll do an offset self-join to achieve the same: 如果不可用,您将执行偏移自联接以实现相同目的:

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

Demo of both: SQL Fiddle 两者的演示: SQL Fiddle

One of the above will work in most dbms (syntax differences of course), but not in MySQL. 以上之一可以在大多数dbms中使用(当然,在语法上也有所不同),但在MySQL中却不能。

If you want to get the average number of days between emails, there is a much easier way. 如果要获取两次电子邮件之间的平均天数,则有一种更简单的方法。

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

The average duration is the maximum open date minus the minimum open date divided by the number of emails minus 1. 平均持续时间是最大打开日期减去最小打开日期除以电子邮件数减去1。

As for the answer to your question, you want to use the lag() function, if your database supports it. 至于问题的答案,如果数据库支持, lag()使用lag()函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM