简体   繁体   中英

SQL - Calculate difference between two records

I have a table that logs logins for each user and the current points total of that user at each login.

What I'd like to do is get their first login for each day and calculate the points difference between their previous days' points total.

To make things clearer, I have written a statement that gets each user's min login per day as follows:

SELECT loginLog.username, A.logInDate, loginLog.pointsTotal
FROM loginLog
JOIN
    (SELECT MIN(logID) AS logID, username, CAST(logInTime AS DATE) AS logInDate
    FROM loginLog
    GROUP BY username, CAST(logInTime AS DATE)) A
ON loginLog.logID = A.logID
ORDER BY username, logInDate DESC

Which produces the following results set:

username    logInDate       pointsTotal
user1       2015-10-28      82685
user1       2015-10-27      51330
user1       2015-10-26      7810
user2       2015-10-28      221223
user2       2015-10-27      207234
user2       2015-10-26      178781
user3       2015-10-28      616120
user3       2015-10-27      598715
user3       2015-10-26      591289
user4       2015-10-28      187654
user4       2015-10-27      198378
user4       2015-10-26      115014
user5       2015-10-28      248138
user5       2015-10-27      224729
user5       2015-10-26      216229
user6       2015-10-28      68546
user6       2015-10-28      24139
user6       2015-10-27      33171
user6       2015-10-27      6459
user6       2015-10-26      6391

So for example, on the first record I'd like to add a column dailyGrowth that would calculate 82685 - 51330, on the second record if would calculate 51330 - 7810 etc etc.

Is this possible?

Since you are using Sql Server 2012 , lead window function is easiest here:

DECLARE @t TABLE
    (
      username VARCHAR(10) ,
      logInDate DATE ,
      pointsTotal INT
    )

INSERT  INTO @t
VALUES  ( 'user1', '2015-10-28', 82685 ),
        ( 'user1', '2015-10-27', 51330 ),
        ( 'user1', '2015-10-26', 7810 ),
        ( 'user2', '2015-10-28', 221223 ),
        ( 'user2', '2015-10-27', 207234 ),
        ( 'user2', '2015-10-26', 178781 )


select *, pointsTotal - lead(pointsTotal) over(partition by username order by logInDate desc) AS dailyGrowth 
from @t

Output:

username    logInDate   pointsTotal dailyGrowth
user1       2015-10-28  82685       31355
user1       2015-10-27  51330       43520
user1       2015-10-26  7810        NULL
user2       2015-10-28  221223      13989
user2       2015-10-27  207234      28453
user2       2015-10-26  178781      NULL

To use your existing query:

select *, pointsTotal - lead(pointsTotal) over(partition by username order by logInDate desc) AS dailyGrowth 
from (existing query goes here)t

Use correlated sub-query to find previous row's pointsTotal :

select t1.username, t1.logInDate, t1.pointsTotal,
       t1.pointsTotal - (select TOP 1 t2.pointsTotal
                         from tablename t2
                         where t2.username = t1.username
                           and t2.logInDate < t1.logInDate
                         order by t2.logInDate desc)
from tablename t1

( SELECT TOP 1 is SQL Server specific. The ANSI SQL way is to add fetch first 1 row only after the ORDER BY clause. Some other dbms products have LIMIT 1 instead.)

Assuming that your result view in your question (with the pointsTotal) is called loginPoints you can join the table with itself using the username and the date. To get the next date you can use DATEADD :

SELECT username,p1.loginDate, p1.pointsTotal-p2.PointsTotal AS dailyGrowth
FROM loginPoints p1 inner join loginPoints p2 on
     p1.username=p2.username AND DATEADD(day,1,p2.loginDate)=p1.loginDate

Note that depending on which DBMS you use, the DATEADD function can be slightly different.

Create a view on your above query and then use analytical lead() function that get next row value and then calculate the difference of first value.

Detail here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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