Хобрук: Ваш путь к мастерству в программировании

О вычислениях между несколькими таблицами, объединенными с помощью 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).

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


  • Сообщение об ошибке (которое вы действительно должны включить) уже говорит вам, что здесь не так: в union все части должны иметь одинаковое количество столбцов. Что касается того, как это исправить: непонятно, что вы пытаетесь сделать (и теперь мне нужно разделить результат этого запроса на данные из другой таблицы), поэтому вы можете уточнить это, желательно с примерами данных, например. несколько строк для обеих частей (до выполнения union) и ожидаемый результат, основанный на них (чтобы понять, что должен делать разделитель, поскольку вы, похоже, не уверены, что это делается с union вообще). 06.09.2018
  • @Solarflare Ваш комментарий содержит ответ. Почему бы не написать ответ? 06.09.2018
  • @O.Jones Фактический вопрос, кажется, это правильно?, и я не совсем уверен, чего он пытается достичь (хотя я почти уверен, что union неверен, больше похоже, что ему нужен join или подзапрос). 06.09.2018
  • Пожалуйста, предоставьте образцы данных и желаемые результаты. 06.09.2018
  • @ Гордон Линофф, привет! Я обновил желаемый результат 06.09.2018
  • @Solarflare, обновил, посмотри плз 06.09.2018
  • Ваш вопрос оформлен так, как будто ваш запрос работает без union (например, если вы замените total_visitors во второй строке на 100 и удалите часть, начинающуюся с union), и вам нужен способ получить фактическое значение общего числа посетителей (одна константа значение для этого запроса) там. Вы можете это проверить? 06.09.2018
  • @Solarflare, да, верно 06.09.2018
  • @Solarflare, может быть, лучше использовать «внутреннюю активность присоединения к activity.login_time = t.payment_time»? 06.09.2018
  • Я не совсем уверен, что вы хотите изменить, но похоже, что это изменит результат внутреннего запроса (p), так как ваше соединение может больше не быть в разное время входа в систему (поэтому вы можете получить больше строк), но опять же , я не уверен, что именно вы хотите там изменить). Я написал вам ответ, но я предполагаю, что ваш запрос (кроме союза) работает и дает вам правильный результат (кроме процента). 06.09.2018

Ответы:


1

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

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.

06.09.2018
  • спасибо за помощь! Это дало мне правильную идею) Я изменил свой код. Только одна беда: он неправильно делит на группы. Общий процент правильный. Согласно моей задаче, группа должна быть разделена, если user_id находится в таблице платежей из-за его платежа, который он когда-либо делал. Но когда я делаю запрос, я думаю, что он начинает делиться на группы из-за его оплаты в период. Я обновил код ниже в вопросе. Пожалуйста, смотрите 07.09.2018
  • @ЕлисейГорьков Это (если я правильно понимаю, что total_visitors работает) новый вопрос, и вы должны задать новый (вы можете оставить мне ссылку на него здесь, если хотите), он лишь незначительно связан с вашим первоначальным вопросом и конкретно с ответом . Так что задайте новый, это не проблема, и на самом деле рекомендуется поддерживать чистоту вопросов. Включите некоторые образцы данных (ввод, результат, который вы получаете, результат, который вы хотите) и попытайтесь уменьшить его до необходимого минимума (t1?), например. вы можете опустить части, связанные с total_visitors, так как теперь вы (надеюсь) знаете, как включить его в измененный код. 07.09.2018
  • посмотрите ссылку stackoverflow.com/questions/52218932/ 07.09.2018

  • 2

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

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

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

    06.09.2018
  • может есть другой способ сделать это? (обновил задачу) 06.09.2018
  • Новые материалы

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

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..

    React Hooks: основы деструктуризации массива
    Kent C. Dodds написал классный пост о том, как грядущая функция React под названием Hooks работает на капоте. Предстоящий хук React useState основан на деструктурировании массива, давайте..

    Пакеты R, используемые в Tesla
    Добро пожаловать обратно! R — очень популярный язык программирования, используемый множеством компаний, включая Tesla! Итак, давайте взглянем на некоторые пакеты R, которые использует Tesla...

    Сокращение и слияние токенов для эффективных моделей VL: обзор
    Часто в задачах, связанных с компьютерным зрением и НЛП, вычислительно затратная и требующая большого объема памяти обработка становится препятствием для более быстрого логического вывода модели, а..