Как рассчитать проценты? - PullRequest
0 голосов
/ 31 августа 2018

Не могли бы вы помочь мне рассчитать процент пользователей, которые сделали платежи? У меня есть две таблицы:

activity
user_id  login_time
201      01.01.2017
202      01.01.2017
255      04.01.2017
255      05.01.2017
256      05.01.2017
260      15.03.2017

2

payments
user_id  payment_date
200      01.01.2017
202      01.01.2017
255      05.01.2017

Я пытаюсь использовать этот запрос, но он вычисляет неверный процент:

SELECT activity.login_time, (select COUNT(distinct payments.user_id) 
from payments where payments.payment_time between '2017-01-01' and 
'2017-01-05') / COUNT(distinct activity.user_id) * 100
AS percent
FROM payments INNER JOIN activity ON  
activity.user_id = payments.user_id and activity.login_time between 
'2017-01-01' and '2017-01-05'
GROUP BY activity.login_time;

Мне нужен результат

01.01.2017  100 % 
02.01.2017  0% 
03.01.2017  0% 
04.01.2017  0% 
05.01.2017 - 50% 

Ответы [ 2 ]

0 голосов
/ 01 сентября 2018

Сначала вам понадобится таблица со всеми днями в диапазоне. Поскольку диапазон небольшой, вы можете построить специальную производную таблицу, используя UNION ALL. Затем осталось присоединиться к платежам и мероприятиям. Сгруппируйте по дням и рассчитайте процент, используя count() s.

SELECT x.day,
       concat(CASE count(DISTINCT a.user_id)
                WHEN 0 THEN
                  1
                ELSE  
                  count(DISTINCT p.user_id)
                  /
                  count(DISTINCT a.user_id)
              END
              *
              100,
              '%')
       FROM (SELECT cast('2017-01-01' AS date) day
             UNION ALL
             SELECT cast('2017-01-02' AS date) day
             UNION ALL
             SELECT cast('2017-01-03' AS date) day
             UNION ALL
             SELECT cast('2017-01-04' AS date) day
             UNION ALL
             SELECT cast('2017-01-05' AS date) day) x
            LEFT JOIN payments p
                      ON p.payment_date = x.day
            LEFT JOIN activity a
                      ON a.login_time = x.day
            GROUP BY x.day;
0 голосов
/ 31 августа 2018

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

select p.cnt / a.cnt
from (select count(distinct user_id) as cnt from activity a) a cross join
     (select count(distinct user_id) as cnt from payment) p;

EDIT:

Вам нужна таблица со всеми датами в диапазоне. Это самая большая проблема.

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

SELECT d.dte,
       ( ( SELECT COUNT(DISTINCT p.user_id)
           FROM payments p
           WHERE p.payment_date >= d.dte and p.payment_date < d.dte + INTERVAL 1 DAY
          ) /
          NULLIF( (SELECT COUNT(DISTINCT a.user_id)
                   FROM activity a
                   WHERE a.login_time >= d.dte and p.login_time < d.dte + INTERVAL 1 DAY
                  ), 0
                 ) as ratio
FROM (SELECT date('2017-01-01') dte UNION ALL
      SELECT date('2017-01-02') dte UNION ALL
      SELECT date('2017-01-03') dte UNION ALL
      SELECT date('2017-01-04') dte UNION ALL
      SELECT date('2017-01-05') dte 
     ) d;

Примечания:

  • Возвращает NULL в дни, когда нет активности. Это имеет больше смысла для меня, чем 0.
  • Используется логика для дат, которая работает как для дат, так и для значений даты / времени.
  • Логика для дат может использовать индекс, который может быть важен для этого типа запроса.
  • Я не рекомендую использовать LEFT JOIN s. Это умножит данные, что может сделать запрос дорогим.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...