SQL - 计算两个记录之间的差异

时间:2015-10-28 09:34:45

标签: sql sql-server sql-server-2012

我有一个表,记录每个用户的登录信息以及每次登录时该用户的当前总数。

我想做的是每天首次登录,并计算前几天总积分之间的积分差异。

为了使事情更清楚,我写了一个声明,每天每个用户的登录次数如下:

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

产生以下结果集:

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

因此,例如,在第一条记录中,我想添加一列dailyGrowth,计算82685 - 51330,在第二条记录上,如果计算51330 - 7810等等。

这可能吗?

4 个答案:

答案 0 :(得分:2)

由于您使用的是Sql Server 2012,因此lead窗口函数最简单:

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

输出:

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

使用现有查询:

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

答案 1 :(得分:0)

使用相关子查询查找上一行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是特定于SQL Server的.ANSI SQL方法是在fetch first 1 row only子句之后添加ORDER BY。其他一些dbms产品则改为LIMIT 1。)

答案 2 :(得分:0)

假设您的问题中的结果视图(使用pointsTotal)被称为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 ,您可以使用用户名和日期将自己加入表中。要获得下一个日期,您可以使用DATEADD

DATEADD

请注意,根据您使用的DBMS,{{1}}功能可能略有不同。

答案 3 :(得分:0)

在上述查询中创建一个视图,然后使用获取下一行值的分析lead()函数,然后计算第一个值的差异。

详情here