У меня есть запрос MySQL (v5.7.26), который выполняется вечно. Вот запрос:
SELECT
ur.user_id AS user_id,
sum(r.duration) AS total_time,
count(user_id) AS number_of_workouts
FROM user_resource ur
INNER JOIN resource r ON r.id = ur.resource_id
WHERE
ur.status = 1
AND NOT ur.action_date IS NULL
AND ur.user_id IN (
SELECT user_id
FROM user_resource ur2
WHERE ur2.action_date >= now() - INTERVAL 2 DAY
)
AND r.type = 'WORKOUT'
GROUP BY ur.user_id;
Я немного поиграл с этим, пытаясь понять, в чем проблема. В целях тестирования я попытался разбить на две части. Итак:
SELECT user_id
FROM user_resource ur2
WHERE ur2.action_date >= now() - INTERVAL 2 DAY;
Возвращает (очень быстро) список user_id пользователя. Когда я подключаю возвращенный результат к первой части запроса, например:
SELECT
ur.user_id AS user_id,
sum(r.duration) AS total_time,
count(user_id) AS number_of_workouts
FROM user_resource ur
INNER JOIN resource r ON r.id = ur.resource_id
WHERE
ur.status = 1
AND NOT ur.action_date IS NULL
AND ur.user_id IN (1,1,1,4,4,5,6,7,7,7);
AND r.type = 'WORKOUT'
GROUP BY ur.user_id
Он работает очень быстро. Мое предположение, что IN (подзапрос) является узким местом.
Я думал о том, чтобы извлечь подзапрос и получить user_ids, а затем использовать его как переменную, но я не уверен, что это хороший подход, и Кроме того, у меня есть проблемы с этим. это моя попытка:
-- first statement
SET @v1 = (SELECT user_id
FROM user_resource ur2
WHERE ur2.action_date >= now() - INTERVAL 2 DAY)
-- second statement
SELECT
ur.user_id AS user_id,
sum(r.duration) AS total_time,
count(user_id) AS prefixes
FROM user_resource ur
INNER JOIN resource r ON r.id = ur.resource_id
WHERE
ur.status = 1
AND NOT ur.action_date IS NULL
AND ur.user_id IN (@v1);
AND r.type = 'WORKOUT'
GROUP BY ur.user_id
Проблема здесь в том, что первый оператор возвращает ошибку:
Подзапрос возвращает более 1 строки.
Ожидаемый результат - user_id, которые могут быть дубликатами. И мне нужны дубликаты для подсчета.
Как я могу это исправить?