计算两次手机充值之间的平均值

时间:2019-04-05 18:57:39

标签: sql sql-server

我有一个手机充电表,如下所示。

<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/chat" android:icon="@drawable/chaticon" android:onClick="chat" android:title="" /> <item android:id="@+id/homePage" android:icon="@drawable/homeicon" android:onClick="homepage" android:title="" /> </menu> 级别,我有特定用户的UserId,Date金额,他在特定日期Balance交流中消耗的金额和voice所消耗的金额(互联网)使用情况。

每当用户为帐户充值时,data就会增加。

所以我想要一个查询,该查询可以帮助我找到每个用户两次充值之间的平均BalanceVoice余额/余额。

Data

Recharge Table

在上表中

给定日期的+--------+-----------+---------+-------+------+ | Userid | Date | Balance | Voice | Data | +--------+-----------+---------+-------+------+ | 1 | 4/5/2018 | 100 | 10 | 15 | //Recharge of 100 | 1 | 4/6/2018 | 75 | 5 | 10 | | 1 | 4/7/2018 | 60 | 10 | 10 | | 1 | 4/8/2018 | 90 | 10 | 20 | //Recharge of 50 | 1 | 4/9/2018 | 60 | 10 | 20 | | 1 | 4/10/2018 | 50 | 20 | 30 |// Recharge of 20 | 2 | 4/1/2018 | 200 | 50 | 40 |// Recharge of 200 | 2 | 4/2/2018 | 110 | 20 | 20 | | 2 | 4/3/2018 | 70 | 20 | 10 | | 2 | 4/4/2018 | 55 | 10 | 40 |// Recharge of 15 | 2 | 4/5/2018 | 5 | 2 | 2 | +--------+-----------+---------+-------+------+ =前一天的(Balance-SUM(Balance + Voice))

您可以看到UserId Data的100减少为75(100-(10 + 15))。

但是在第三行(1)中,他的充值金额为50,因此余额为90而不是40。

所以我想找到Date = 4/8/2018的平均VoiceData列在100和90之间

下面是我想要的输出

UserId = 1

我知道这个问题很难理解,但我已经尽力解释了。

如有任何歧义,请随时询问。

3 个答案:

答案 0 :(得分:1)

我添加了两个新列来确定充值信息: 我认为您可以在另一张表中存储充值信息,如果您可以像我执行此查询一样放置该信息,则可以使用。

DECLARE @tbl table(
    Userid int,
    Date    datetime,
    Balance int,
    Voice int,
    Data int,
    Recharge int,
    RechargeSN int
)

INSERT INTO @tbl(    Userid,    [Date],    Balance,    Voice,    Data,Recharge,RechargeSN) VALUES(1,'4/5/2018'  ,     100 ,    10 ,   15,100,3)
INSERT INTO @tbl(    Userid,    [Date],    Balance,    Voice,    Data,Recharge,RechargeSN) VALUES(1,'4/6/2018'  ,      75 ,     5 ,   10,0,3)
INSERT INTO @tbl(    Userid,    [Date],    Balance,    Voice,    Data,Recharge,RechargeSN) VALUES(1,'4/7/2018'  ,      60 ,    10 ,   10,0,3)
INSERT INTO @tbl(    Userid,    [Date],    Balance,    Voice,    Data,Recharge,RechargeSN) VALUES(1,'4/8/2018'  ,      90 ,    10 ,   20,50,2)
INSERT INTO @tbl(    Userid,    [Date],    Balance,    Voice,    Data,Recharge,RechargeSN) VALUES(1,'4/9/2018'  ,      60 ,    10 ,   20,0,2)
INSERT INTO @tbl(    Userid,    [Date],    Balance,    Voice,    Data,Recharge,RechargeSN) VALUES(1,'4/10/2018' ,      50 ,    20 ,   30,20,1)

INSERT INTO @tbl(    Userid,    [Date],    Balance,    Voice,    Data,Recharge,RechargeSN) VALUES(2,'4/1/2018'  ,     200 ,    50 ,   40,200,2)
INSERT INTO @tbl(    Userid,    [Date],    Balance,    Voice,    Data,Recharge,RechargeSN) VALUES(2,'4/2/2018'  ,     110 ,    20 ,   20,0,2)
INSERT INTO @tbl(    Userid,    [Date],    Balance,    Voice,    Data,Recharge,RechargeSN) VALUES(2,'4/3/2018'  ,      70 ,    20 ,   10,0,2)
INSERT INTO @tbl(    Userid,    [Date],    Balance,    Voice,    Data,Recharge,RechargeSN) VALUES(2,'4/4/2018'  ,      55 ,    10 ,   40,15,1)
INSERT INTO @tbl(    Userid,    [Date],    Balance,    Voice,    Data,Recharge,RechargeSN) VALUES(2,'4/5/2018'  ,      5  ,    2  ,   2,0,1)

--SELECT * FROM @tbl t

SELECT userid, RechageDate  = max(date), Avg_Voice = (cast(SUM(voice) AS numeric) / Count(voice))  , Avg_Data = cast(SUM(Data) AS numeric) / Count(Data) *1.00 
--, t.RechargeSN 
FROM @tbl t
GROUP BY t.Userid, t.RechargeSN
ORDER BY t.Userid

答案 1 :(得分:1)

由于您尚未发布解决此问题的任何尝试,但是对数据有所了解,所以我认为您只需要被赋予广泛的策略即可开始关注,并且可以从那里开始进行编码。

>

使用按UserID分区的LAG(),可以将每一行连接到上一行。您已经说过您了解这一点(余额-SUM(语音+数据)),因此在任何情况下都不正确的情况下,那么您知道已经找到行进行了充值。

您可以在CTE中创建一个人工列(例如HasRecharge),该列使用CASE表达式进行测试,并为有充值的行返回1,为没有充值的行返回0。 / p>

然后,您可以执行第二个CTE,从第一个CTE WHERE HasRecharge = 1中进行选择,然后在其中EXISTS()前一个行也HasRecharge = 1。并计算另外两列:

在此充值和上一次充值之间的总和为Voice + Data(再次使用LAG(),但这一次WHERE HasRecharge = 1)

此充电与最后一次充电之间有COUNT行。

您从第二CTE进行的最终SELECT只需将SUM列除以COUNT列即可得到平均值。

答案 2 :(得分:0)

如果您有一个包含当日费用和前一天费用的平桌,此问题将变得更加简单。请注意,这仅在您的数据集具有连续的日期范围时才有效。

以下查询当然需要进行编辑:

Select 
 currentday.Date,
 currentday.user,
 currentday.balance - prevday.balance - (currentday.voice+currentday.data) as charge,
 currentDay.voice,
 currentDay.data,
 --The above column will tell you what the difference 
 --is between the expected balance, and should 
 --resolve to the charge for the day
 GETDATE() as nextCharge
 --leave this empty, use GETDATE() to force it to be a datetime
into ##ChargeTable
from [RechargeTable] currentday
 left join [RechargeTable] prevday
   on DATEADD(d,1,prevday.Date) = currentday.Date
      AND prevday.user = currentday.user

现在,我们知道用户何时收费。费用栏将为正。

Select
 user, 
 date
into ##uniquedates
from ##charge
where charge>0

现在我们有了日期,我们需要回到第一个临时表并用下一个日期更新它。 (不确定别名更新的语法)。

update ##ChargeTable up
set 
nextCharge = (
    select 
     date 
    from ##uniquedates 
    where up.user == user AND date > up.date
)  

现在,我们可以在表上进行一些子选择,以获取所需的数据。

select 
 user,
 (select 
       avg(voice)
      from ##ChargeTable 
      where user = ct.user 
       and date>=ct.date 
       and date<=ct.nextCharge) as AvgVoice,
 (select 
       avg(data)
      from ##ChargeTable 
      where user = ct.user 
       and date>=ct.date 
       and date<=ct.nextCharge) as AvgData
from ##ChargeTable ct
where nextCharge is not null and charge>0