Рассчитать среднее значение между двумя зарядками сотового телефона - PullRequest
3 голосов
/ 05 апреля 2019

У меня есть таблица пополнения счета мобильного телефона, как показано ниже.

В том, что на уровне UserId,Date у меня есть сумма Balance конкретного пользователя, сумма, которую он потребил в определенный день для voice общения, и сумма, которая была израсходована для использования data (Интернет).

Всякий раз, когда пользователь пополняет свою учетную запись, Balance увеличивается.

Итак, я хочу запрос, который поможет мне найти среднюю сумму Voice и 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 = Предыдущий день (Balance - SUM (Voice + Data))

Как вы можете видеть для UserId 1 100 уменьшается до 75 (100 - (10 + 15)).

Но в третьем ряду (Date = 4/8/2018) он перезаряжается на сумму 50, благодаря чему его баланс становится 90 вместо 40.

Итак, я хочу найти средние столбцы Voice и Data между 100 и 90 для UserId = 1

Ниже вывод, который я хочу

+--------+-------------+-----------+----------+
| UserID | RechageDate | Avg_Voice | Avg_Data |
+--------+-------------+-----------+----------+
|      1 | 4/8/2018    |      8.33 |    11.66 |
|      1 | 4/10/2018   |        10 |       20 |
|      2 | 4/4/2018    |      27.5 |       25 |
+--------+-------------+-----------+----------+

Я знаю, что этот вопрос трудно понять, но я изо всех сил пытался его объяснить.

Пожалуйста, не стесняйтесь спрашивать в случае любой двусмысленности.

Ответы [ 3 ]

1 голос
/ 05 апреля 2019

Поскольку вы не опубликовали ни одной попытки решить эту проблему, но продемонстрировали понимание данных, я полагаю, что вам просто нужно дать широкую стратегию, чтобы начать следовать, и вы сможете обрабатывать кодирование оттуда.

Используя LAG (), разделенную по UserID, вы можете присоединить каждую строку к предыдущей строке.Вы уже заявили, что понимаете это (Баланс - СУММА (Голос + Данные)), поэтому в любом СЛУЧАЕ, где это не так, вы знаете, что нашли строку, в которой было выполнено пополнение.

Вы можете создать искусственный столбец (например, HasRecharge) в CTE, который использует выражение CASE для проверки этого и возвращает 1 для строк, которые имеют пополнение, и 0 для строк, которые не имеют.

Затем вы можете сделать второй CTE, в котором вы выбираете из первого CTE, ГДЕ HasRecharge = 1 и ГДЕ существует () предыдущая строка, которая также HasRecharge = 1.И вычислите два дополнительных столбца:

СУММА Voice + Data между этим пополнением и последним пополнением (снова с использованием LAG (), но на этот раз, ГДЕ HasRecharge = 1)

COUNT строк между этим пополнением и последним.

Ваш последний SELECT из 2-го CTE получит среднее значение, просто поделив столбец SUM на столбец COUNT.

1 голос
/ 05 апреля 2019

Я добавил два новых столбца для определения информации о пополнении счета: я думаю, что у вас есть информация о пополнении счета в другой таблице, если вы можете поместить эту информацию, как я сделал, этот запрос будет работать.

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
0 голосов
/ 05 апреля 2019

Эта проблема упрощается, когда у вас плоский стол, содержащий дневную плату и плату за предыдущий день. Обратите внимание, что это будет работать только в том случае, если ваш набор данных имеет непрерывный диапазон дат.

Следующие запросы необходимо будет отредактировать, конечно:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...