LEFT JOIN stats AS s
. В лабораторном примере user_id + date
не обязаны быть уникальными, поскольку PK состоит из user_id + date + type
. Но это вроде как сути задачи не меняет — нужно получить _одну_ последнюю запись статистики.SELECT u.id, u.*, ms.*
FROM user u
LEFT JOIN ( # фильтруем записи с последней датой
SELECT ss.user_id, MAX(ss.date), ss.type AS max_date
FROM stats AS ss
GROUP BY ss.user_id
) AS ms ON ms.user_id = u.id
SELECT u.id, u.*, ms.*
FROM user u
LEFT JOIN (
SELECT ss.user_id, MAX(ss.date), ss.type AS max_date
FROM stats AS ss
WHERE ss.type = 'тип №8' # дополнительное условие фильтрации по типу
GROUP BY ss.user_id
) AS ms ON ms.user_id = u.id
Не работает ваш запрос потому, что вы из подзапроса обратно выбираете тот же самый user_id, который «подали вовнутрь»
SELECT U.*, S.*
FROM `user` AS U
LEFT JOIN stats AS S ON 1 = (
SELECT S2.user_id
FROM stats AS S2
WHERE S2.user_id = 1 # это условие вообще не работает - выбираются все записи из stats
ORDER BY S2.date DESC
LIMIT 1
)
LIMIT 1
в подзапросе — должна быть «склеена» только одна запись из таблицы stats? А с таким запросом к каждому юзеру джойнятся все записи из stats. return DB->fetch("SELECT code FROM table WHERE id = '$id'");
Мне не то, чтобы не нравится, я использую этот подход, когда набор данных статический, либо меняется редко (~ раз в полгода). А тут динамика типов статистики довольно динамична. И меня смущает итоговый набор в + "...30-60 полей к основным данным юзера." При этом данные статистики обновляются по каждой записи ~ раз в минуту.
Нет, но денормализацию я обычно провожу после проектирования полной структуры БД.
Я просто прикидываю что количество запросов на выборку = запросам на вставку, ну может SELECT'ов будет на 20% больше. В оригинале это не юзеры, а прокси сервера и после запроса и отработки прокси — логируем результат. Юзерами, пожалуй, не стоило называть лабораторную сущность, слишком упростил.
Получается для одной таблицы статистики — мы вставили новый лог и забыли. А в случае с дополнительной таблицей с актуальными данными, нужно каждый раз проверять существование записи и либо вставлять новую, либо обновлять существующую. Вот этот момент меня и смущает.
Я с ходу не могу сказать что будет быстрее. И как лучше распределить нагрузку — на выборку или на вставку.
Похоже нужно проверять на средних объемах данных.
Спасибо за подсказку и за статью, не читал.