@fman2

Как правильно переписать SQL запрос?

Добрый день, дорогие друзья.

Есть база с пользователями users на 30к пользователей:
user_id
user_name

Есть база с некоторыми числами values, которые добавляются каждый день, но не на каждого пользователя (каждый день из 30к пользователей порядка 25к чисел добавляются)
value_id,
user_id
value
date (ДД.ММ.ГГГГ)

Необходимо получить все значения (value) за сегодняшний день и за прошлый, а также эти значения сравнить (value предыдущего дня > value текущего дня). Но соответственно нужно как-то сделать выборку лишь по тем пользователям, у которых запись в таблице values есть за два дня.
Сейчас мы делаем это вложенным циклом (да простите меня за это) примерно вот так:

for ($i=0; $i<count...; $i++) {
     for ($j=0; $j<count...; $j++) {
          // тут происходит сравнения айди пользователей из данных за вчера и сегодня
          // и если они совпадают - делаем сравнение чисел


Когда пользователей было 200, все работало быстро, но на проверке 30 000 записей из таблицы value скрипт вешается капитально и нужно придумать другой вариант.
  • Вопрос задан
  • 2583 просмотра
Пригласить эксперта
Ответы на вопрос 3
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Для начала рекомендую преобразовать поле `date` в тип DATE, тогда с ним можно будет работать стандартными функциями MySQL и строить по нему индексы.
SELECT `today`.`user_id`, `today`.`value`, `yesterday`.`value`, `users`.`name`
    FROM `values` AS `today`
    INNER JOIN `values` AS `yesterday` ON `yesterday`.`user_id` = `today`.`user_id`
    LEFT JOIN `users` ON `users`.`id` = `values`.`user_id`
    WHERE `today`.`date` = CURDATE()
        AND `yesterday`.`date` = CURDATE()-INTERVAL 1 DAY
        AND `yesterday`.`value` > `today`.`value`
Ответ написан
Комментировать
@Arik
Примерно так должно быть, но не тестировал, нет таблиц живых
SELECT
    a.`user_id`,
    b.`user_name`,
    a.`date`,
    a.`value`
FROM
    `values` AS a
JOIN
    `users` AS b
ON
    b.`user_id` = a.`user_id`
WHERE
    a.`date` = "26.12.2014" 
    AND
    a.`value` >
        (
        SELECT
            c.`value`
        FROM
            `values` AS c
        WHERE
            c.`user_id` = a.`user_id`
            AND
            c.`date` = "25.12.2014"
        LIMIT 1
        )
Ответ написан
@melnikov_m
Если числа в таблицу "values" добавляются только они раз в сутки, как вариант оптимизации могу предложить
1) взять запрос выше и запускать его раз в день по крону.
2) Получившиеся значения записывать в "users" (конечно же не актуальные значения за прошлый день нужно удалять).
Практическая выгода: Будите получать value простым селектом из одной таблицы. Не надо будет постоянно обращаться к базе "values", ускорится загрузка страницы, экономится память. Может сейчас не так заметно, но если база будет расширяться, в будущем сильно вам облегчит жизнь.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы