О расчетах среди нескольких таблиц, объединенных с UNION - PullRequest
0 голосов
/ 06 сентября 2018

У меня сложный запрос, и теперь мне нужно разделить результат этого запроса на данные из другой таблицы. Используется UNION. Это правильно? Почему я не работаю?

SELECT * from (select IFnull(t.diapason,'total') as diapason, count(distinct 
user_id) / total_visitors*100 AS 'percent_of_users'
FROM 
(SELECT p.user_id, p.amount as total, CASE  
when amount<10 then '0-10' 
when amount>=10 then '10 +' END AS diapason
FROM 
    (SELECT payments.user_id, SUM(amount) AS amount 
    FROM payments INNER JOIN 
   (SELECT DISTINCT user_id, login_time FROM activity where login_time 
between '2018-04-12' and '2018-04-18') a 
ON payments.user_id = a.user_id and a.login_time = payments.payment_time 
GROUP BY payments.user_id) p
) t
  GROUP BY diapason WITH ROLLUP) as t1

UNION
SELECT COUNT(distinct user_id) as total_visitors FROM activity where 
login_time between '2018-04-12' and '2018-04-18'
ORDER BY percent_of_users desc;

Я сделал UNION, потому что мне нужно получить total_visitors.

Спасибо!

Результат

diapason    percent_of_visitors
0-10          ...%
10+           ...%

Для расчета процента_фот_пользователей (новое значение Activity.user_id / старое значение Activity.user_id).

Но я не знаю, как получить доступ к старому значению. Можете ли вы дать мне подсказки?

Ответы [ 2 ]

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

Начиная с вашего рабочего запроса

SELECT ifnull(t.diapason,'total') as diapason,
   COUNT(DISTINCT user_id) AS user_count
FROM ...

Вы можете включить total_visitors с подзапросом:

SELECT ifnull(t.diapason,'total') as diapason,
  COUNT(DISTINCT user_id) * 100 /
     (SELECT COUNT(distinct user_id) 
      FROM activity WHERE ...) as percent_of_users
FROM (...) t
GROUP BY diapason WITH ROLLUP
ORDER BY percent_of_users DESC

В качестве альтернативы, вы можете использовать join (что ближе к структуре запроса, которую вы намеревались):

SELECT t1.diapason, 
  t1.user_count * 100 / tv.total_users as percent_of_users
FROM ( SELECT ifnull(t.diapason,'total') as diapason,
         COUNT(distinct user_id) AS user_count
       FROM ...
     ) as t1
CROSS JOIN (SELECT COUNT(distinct user_id) as total_visitors 
      FROM activity WHERE ...) as tv
ORDER BY percent_of_users DESC

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

В обоих случаях общее количество будет рассчитываться только один раз, тем не менее, MySQL выполнит два запроса немного по-разному (хотя это не должно иметь большого эффекта). Возможно, вы захотите включить проверку на счет 0 (и, следовательно, деление на 0), хотя здесь этого не должно быть.

Примечание: для MySQL 8+ вы можете немного упростить (и уточнить) свой код, если используете cte , поскольку в настоящее время вы в основном повторяете код подзапроса a дважды (один раз в Ваш фактический запрос, один раз при расчете общего количества), который может вызвать раздражение и замешательство, если он сложнее простого where.

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

Вы пытаетесь что-то сделать с этим типом шаблона.

 SELECT a, b, c FROM tbl 
 UNION
 SELECT d FROM tbl

Вы не можете этого сделать и торговать ;. Два набора результатов в объединении должны иметь одинаковое количество столбцов, и каждый столбец должен иметь одинаковый тип данных в каждом из наборов результатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...