SQL запрос, который дает мне процент пользователей, которые не запускают игру в день - PullRequest
2 голосов
/ 12 февраля 2020

Я бы очень признателен за помощь по SQL запросу, который я пытался написать.

Фон :

Каждый раз, когда пользователь играет в игру, в таблице game_runs создается запись вместе с их user_id и run_date (a MySQL отметка времени).

  • Когда пользователь успешно играет в игру, он получает оценку больше 0.
  • Если игра не запустилась (например, возможно, она упала), оценка 0

Таблица выглядит примерно так:

 id  |     run_date         |  user_id   |   score   
-------------------------------------------------------
 1   |  2020-02-02 00:20:00 |    10      |     0      |   
 2   |  2020-02-02 01:50:10 |    10      |    40      |   
 3   |  2020-02-02 03:40:20 |    11      |    80      |   

 4   |  2020-02-03 03:20:14 |    20      |    80      |   
 5   |  2020-02-03 12:20:14 |    21      |     0      |   

 6   |  2020-02-04 06:20:42 |    50      |     0      |   
 7   |  2020-02-04 11:15:00 |    50      |     0      |
 8   |  2020-02-04 12:10:46 |    51      |    70      |   

 9   |  2020-02-05 00:15:00 |    60      |     0      |
10   |  2020-02-05 01:10:40 |    61      |     0      |   

Я бы хотел выяснить, какой процент пользователей не удалось запустить игра в день.

В приведенном выше примере, я надеюсь, что я могу сгенерировать:

date         |   percent_users_who_failed_to_run_the_game
-------------------------------------------------------------
2020-02-02   |   0
2020-02-03   |   0.5
2020-02-04   |   0.5
2020-02-05   |   1

Обратите внимание, как на 2020-02-02, процент пользователей, которые не смогли запустить игра составляет 0% (т.е. каждый выиграл хотя бы один раз). Это связано с тем, что на 2020-02-02 было три запуска:

  • id = 1: user_id 10 не удалось запустить его изначально (оценка = 0)
  • id = 2: user_id 10 успешно во второй раз (оценка = 40)
  • id = 3: user_id 11 успешно

Поскольку оба пользователя были успешными в тот день, процент пользователей, которые провал был 0%.

Мне бы очень хотелось узнать, как начать. Я использую mySQL v8 +, поэтому имейте доступ к оконным функциям, если это необходимо (мое исследование говорит мне, что они могут помочь, но не смог написать запрос, который делает это).

Я думаю, что правильная логика c была бы чем-то вроде выяснения% пользователей, у которых есть MAX(score) = 0, но не знаете, как написать запрос.

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

Спасибо!

Ответы [ 2 ]

5 голосов
/ 12 февраля 2020

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

SELECT  CAST(Run_Date AS DATE) AS RunDate,
        User_ID,
        MAX(Score) AS Score
FROM    YourTable
GROUP BY CAST(Run_Date AS DATE), User_ID;

Затем вы можете поместить это в подзапрос и рассчитать свой процент:

SELECT  RunDate,
        COUNT(CASE WHEN Score = 0 THEN 1 END) / SUM(1.0) AS Failed_Percent
FROM    (   SELECT  CAST(Run_Date AS DATE) AS RunDate,
                    User_ID,
                    MAX(Score) AS Score
            FROM    YourTable
            GROUP BY CAST(Run_Date AS DATE), User_ID
        ) AS t
GROUP BY RunDate;

Пример на SQL Fiddle

Вы также можете достичь этого без подзапроса, используя COUNT(DISTINCT):

SELECT  CAST(Run_Date AS DATE) AS RunDate,
        1 - (1.0 * COUNT(DISTINCT CASE WHEN Score > 0 THEN User_ID END) 
            / COUNT(DISTINCT User_id)) AS Failed_Percent
FROM    YourTable
GROUP BY CAST(Run_Date AS DATE);

Пример на SQL Fiddle

Это действительно делает обратную логику c, но результат тот же. Соответствующие части:

COUNT(DISTINCT CASE WHEN Score > 0 THEN User_ID END)

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

COUNT(DISTINCT User_id) 

Дает общее количество зарегистрированных пользователей. запись на эту дату. Первое, разделенное на второе, дает процент успешных пользователей, поэтому нам нужно минус это от 1, чтобы получить процент неудачных. Я умножил одно из значений на 1,0, чтобы неявно преобразовать его в десятичное число, чтобы избежать целочисленного деления

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

1 голос
/ 12 февраля 2020

Вы можете сделать это без подзапроса:

select date(run_date) as dte,
       1 - count(distinct case when score > 0 then user_id end)) / count(distinct user_id)
from t
group by dte;

Это число пользователей, которые успешно запускали игру каждый день. 1 - <this amount> - число неудачных попыток.

...