SQL从给定日期计算每日利润

时间:2014-08-21 10:21:57

标签: sql sql-server

我目前正在尝试计算自8月14日以来每个帐户的每日利润。

我有以下SQL,它可以在最后一天获得利润(通过昨天每个帐户首次登录和今天每个帐户的第一次登录计算),但如何进一步获取每日利润自2008年8月以来的每个帐户?

SELECT A.accountName, B.date AS Date, (A.total - B.total) AS Profit 
FROM
    (SELECT accountName, CAST(logInTime AS DATE) AS date, total
     FROM LoginLog
     WHERE logID IN (SELECT MIN(logID) 
                     FROM LoginLog 
                     WHERE logInTime > CAST(GETDATE() AS DATE) 
                     GROUP BY accountName, CAST(logInTime AS DATE)
                     )
     ) A
LEFT JOIN
    (SELECT accountName, CAST(logInTime AS DATE) AS date, total
     FROM LoginLog
     WHERE logID IN (SELECT MIN(logID) 
                     FROM LoginLog 
                     WHERE logInTime > CAST(DATEADD(DAY,-1,GETDATE()) AS DATE) 
                       AND logInTime < CAST(GETDATE() AS DATE) 
                     GROUP BY accountName, CAST(logInTime AS DATE) 
                     )
      ) B
ON A.accountName = B.accountName
ORDER BY accountName

LoginLog表中的记录示例如下:

accountName           logInTime                   total
--------------------- --------------------------- -----------
AddableDeer621        2014-08-21 09:26:58.000     14131
StewyClown7           2014-08-21 09:20:17.000     37550
StewyClown7           2014-08-21 09:04:26.000     37550
AddableDeer621        2014-08-20 16:36:13.000     11864
StewyClown7           2014-08-20 16:34:03.000     37550
StewyClown7           2014-08-20 16:29:40.000     37550
AddableDeer621        2014-08-20 15:18:51.000     10038
StewyClown7           2014-08-20 15:12:10.000     33750
AddableDeer621        2014-08-20 14:44:41.000     9077
StewyClown7           2014-08-20 14:38:00.000     33750
AddableDeer621        2014-08-20 14:10:48.000     9077
StewyClown7           2014-08-20 14:03:55.000     33750
AddableDeer621        2014-08-20 12:53:15.000     9077
StewyClown7           2014-08-20 12:46:36.000     33750
AddableDeer621        2014-08-20 11:58:59.000     9077
AddableDeer621        2014-08-20 05:13:24.000     9077
AddableDeer621        2014-08-20 03:25:01.000     8827
AddableDeer621        2014-08-20 02:16:04.000     7622
AddableDeer621        2014-08-20 00:00:02.000     7622
AddableDeer621        2014-08-19 22:48:57.000     7622
AddableDeer621        2014-08-19 21:39:45.000     5777
AddableDeer621        2014-08-19 20:30:45.000     5777
AddableDeer621        2014-08-19 19:22:03.000     4912

我希望结果显示的示例如下:

accountName           Date           Profit
--------------------- -------------- -----------
AddableDeer621        2014-08-20     6509
StewyClown7           2014-08-20     4000
AddableDeer621        2014-08-19     2710

如果您需要更多信息,请告诉我

3 个答案:

答案 0 :(得分:0)

SELECT A.accountName, B.date AS Date, (A.total - B.total) AS Profit 
FROM
(SELECT accountName, CAST(logInTime AS DATE) AS date, total
 FROM LoginLog
 WHERE logID IN (SELECT MIN(logID) 
                 FROM LoginLog 
                 WHERE logInTime > '2014-08-14 00:00:00.000'
                 GROUP BY accountName, CAST(logInTime AS DATE)
                 )
 ) A
LEFT JOIN
(SELECT accountName, CAST(logInTime AS DATE) AS date, total
 FROM LoginLog
 WHERE logID IN (SELECT MIN(logID) 
                 FROM LoginLog 
                 WHERE logInTime > CAST(DATEADD(DAY,-1,GETDATE()) AS DATE) 
                   AND logInTime < CAST(GETDATE() AS DATE) 
                 GROUP BY accountName, CAST(logInTime AS DATE) 
                 )
  ) B
ON A.accountName = B.accountName
ORDER BY accountName

答案 1 :(得分:0)

我甚至不确定你的问题是什么(样本数据和期望的结果真的帮助)。但您可以大大简化现有查询。您可以使用row_number()识别每天的第一条记录,然后使用条件聚合来获得所需的结果:

select ll.accountName, 
       max(case when IsToday = 0 then ll.logindate end) as date,
       sum(case when IsToday = 1 then ll.total else -ll.total end) as profit
from (select ll.*,
             (case when cast(logInTime as date) = cast(getdate() as date) then 1 else 0
              end) as IsToday,
             cast(logintime as date) as logindate,
             row_number() over (partition by accountname, cast(logintime as date order by logid) as seqnum
      from loginlog ll
      where logInTime > CAST(DATEADD(DAY, -1, GETDATE()) AS DATE)
     ) t
where seqnum = 1
order by ll.accountName;

此查询更容易推广到其他日期。

答案 2 :(得分:0)

第二次尝试

WITH FirstLogin_CTE
AS (
    -- Get the first login for all days
    SELECT accountName, CAST(logInTime AS DATE) AS date, MIN(logID) MinLogId
    FROM LoginLog
    WHERE logInTime >= '2014-08-14'
    GROUP BY accountName, CAST(logInTime AS DATE)
)

SELECT X.accountName, X.PreviousDate As Date, (A.total - B.total) AS Profit 
FROM (
    SELECT cte.accountName, cte.date As CurrentDate, cte.MinLogId as CurrentId, prev.date As PreviousDate, prev.MinLogId as PreviousId
    FROM FirstLogin_CTE cte
    LEFT JOIN FirstLogin_CTE prev ON prev.accountName = cte.accountName AND prev.date = DateAdd(day, -1, cte.date)
) X
INNER JOIN LoginLog A
    ON A.accountName = X.accountName AND A.logID = X.CurrentId
INNER JOIN LoginLog B
    ON B.accountName = X.accountName AND B.logID = X.PreviousId