• Подзапрос в условии ON для LEFT JOIN'а в MySQL

    Sorbing
    @Sorbing Автор вопроса
    Как хорошо, что на хабре уже есть перевод статьи с вики Slowly changing dimension. Инглиш читаю в парес с GTranslate'ом.
    Если не нравится паттерн с созданием аттрибутов статистики в сущности клиента..

    Мне не то, чтобы не нравится, я использую этот подход, когда набор данных статический, либо меняется редко (~ раз в полгода). А тут динамика типов статистики довольно динамична. И меня смущает итоговый набор в + "...30-60 полей к основным данным юзера." При этом данные статистики обновляются по каждой записи ~ раз в минуту.
    Вам действительно принципиально гонять запросы на получение и исторических и актуальных данных по одной таблице?

    Нет, но денормализацию я обычно провожу после проектирования полной структуры БД.
    Я просто прикидываю что количество запросов на выборку = запросам на вставку, ну может SELECT'ов будет на 20% больше. В оригинале это не юзеры, а прокси сервера и после запроса и отработки прокси — логируем результат. Юзерами, пожалуй, не стоило называть лабораторную сущность, слишком упростил.
    Получается для одной таблицы статистики — мы вставили новый лог и забыли. А в случае с дополнительной таблицей с актуальными данными, нужно каждый раз проверять существование записи и либо вставлять новую, либо обновлять существующую. Вот этот момент меня и смущает.
    Я с ходу не могу сказать что будет быстрее. И как лучше распределить нагрузку — на выборку или на вставку.
    Похоже нужно проверять на средних объемах данных.
    Спасибо за подсказку и за статью, не читал.
  • Подзапрос в условии ON для LEFT JOIN'а в MySQL

    Sorbing
    @Sorbing Автор вопроса
    Исходя из первоначальной задачи, я не совсем понимаю предназначение второго джойна LEFT JOIN stats AS s. В лабораторном примере user_id + date не обязаны быть уникальными, поскольку PK состоит из user_id + date + type. Но это вроде как сути задачи не меняет — нужно получить _одну_ последнюю запись статистики.

    1. Например нужно получить последнюю статсу по любому типу (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 
    

    … получили. На тестовых данных все сходится. Второй джойн не нужен.

    2. Нужно получить последнюю статистику с учетом типа:
    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 
    

    Я пока не вижу надобности в дополнительном джойне. Может у нас не сходятся представления об условиях задачи? Или в моем запросе (без втого джойна) мы будем получать дополнительные поля таблицы stats в случайном порядке из-за группировки?
  • Подзапрос в условии ON для LEFT JOIN'а в MySQL

    Sorbing
    @Sorbing Автор вопроса
    Все, разобрался с внутренними противоречивыми чувствами, или проще — я тупил, это же JOIN :). Благодарю за помощь. Буду пересматривать структуру БД.
  • Подзапрос в условии ON для LEFT JOIN'а в MySQL

    Sorbing
    @Sorbing Автор вопроса
    Это да, сенк. А что скажете про добавление суррогатного ключа вместо составного primary key из 3-х полей?
  • Подзапрос в условии ON для LEFT JOIN'а в MySQL

    Sorbing
    @Sorbing Автор вопроса
    Я уже думаю об этом). Юзеров предполагается ~10 000, по каждому юзеру в день добавляется до 2-3 тыщ записей статисти. Тут вопрос в том, что есть ТИП записи в таблице статистики. И держать последнюю дату придется по каждому типу. Типы добавляются по мере необходимости, предполагается 10-20 типов в итоге.
    Получается, в статистике есть допустим, 3 поля с данными юзера + дата + тип.
    Если хранить последние данные истории (статистики) в самой таблице user:
    1. По мере необходимости нужно будет добавлять новые поля когда появляется новый ТИП статистических данных;
    2. В итоге полей будет 3 * N типов, это еще плюс 30-60 полей к основным данным юзера. Как-то тоже не гуд.
    Может у Вас есть какие-то мысли по этому поводу? Спасибо.
  • Подзапрос в условии ON для LEFT JOIN'а в MySQL

    Sorbing
    @Sorbing Автор вопроса
    Если убрать LIMIT 1 из подзапроса, получим: "[Err] 1242 — Subquery returns more than 1 row"
  • Подзапрос в условии ON для LEFT JOIN'а в MySQL

    Sorbing
    @Sorbing Автор вопроса
    Читаю:
    Не работает ваш запрос потому, что вы из подзапроса обратно выбираете тот же самый user_id, который «подали вовнутрь»

    ОК, я передаю в условие склейки просто число = 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.
  • Подзапрос в условии ON для LEFT JOIN'а в MySQL

    Sorbing
    @Sorbing Автор вопроса
    Я говорил, что "… нужно получить дополнительные поля, которые я не указывал в упрощенной схеме..".
    В табл. stats есть еще 5 полей, которые необходимо получить. Считаю вариант, предложенный FreeTibet оптимальным. По Вашему, в моем случае, нужно JOIN'ить таблицу stats для каждого поля этой таблицы.
    Если нужно только одно поле (дата) — тогда да. Все же спасибо.
  • Подзапрос в условии ON для LEFT JOIN'а в MySQL

    Sorbing
    @Sorbing Автор вопроса
    Да, в данном запросе условие WHERE user.id = 1 нельзя опускать, иначе джойнится последняя дата любого user.id.
    Для выбора одной записи будет работать. Но не для всех записей таблицы.
    Хотя это моя оплошность — я привел пример с WHERE U.id = 1, но не указал что это опционально. Спасибо.
  • Стиль написания нативных SQL-запросов?

    Sorbing
    @Sorbing Автор вопроса
    На счет переносов с конкатенацией — я не сторонник. По мне более читабельно переносить ключевые слова внутри строки — более читабельно.
  • Стиль написания нативных SQL-запросов?

    Sorbing
    @Sorbing Автор вопроса
    Доступно. Спасибо.
  • Стиль написания нативных SQL-запросов?

    Sorbing
    @Sorbing Автор вопроса
    >… как форматируются строки у вас в проекте…
    т.е. по первому варианту?
    Находите предложенный Вами вариант лучше (удобней), чем вариант №2 из первого поста? Если да, то чем?
  • Стиль написания нативных SQL-запросов?

    Sorbing
    @Sorbing Автор вопроса
    А если строка? Чем чревато писать запросы в таком формате?
    $sql = "SELECT code FROM table WHERE name = '$name'";
    
  • Стиль написания нативных SQL-запросов?

    Sorbing
    @Sorbing Автор вопроса
    Вы, наверное, не используете форматирование? Вам не принципиальны отступы и переносы строк?
    Для командной разработки обычно оговаривают стиль кодирования. На скорость это не влияет, но «читать» легко и приятно.
  • Стиль написания нативных SQL-запросов?

    Sorbing
    @Sorbing Автор вопроса
    1. Согласен.
    2. Вставляем, т.к. некоторые скрипты «системные» — нужна максимальная производительность, строк ~ млн. поэтому (скорее всего) отказались от PDO. Считает строка запроса вида:
    return DB->fetch("SELECT code FROM table WHERE id = '$id'");
    

    действительно ужасная?
    Но тут есть и второй момент, в проекте $DB — это глобальная переменная (я заведомо опустил это дабы не уходить от основного вопроса). Вот это я считаю ужасным. Да, проект требует рефакторинга, но как всегда акцент сделан на сроки. Так что увы, это больной вопрос. Но Ваши замечания верны.
  • Блочные комментарии полностью сворачиваются (Eclipse, NetBeans). Почему?

    Sorbing
    @Sorbing Автор вопроса
    Я написал, но, походу промахнулся. С инглишем у меня не ахти. Не подскажете линк?
  • Блочные комментарии полностью сворачиваются (Eclipse, NetBeans). Почему?

    Sorbing
    @Sorbing Автор вопроса
    Блин! Знал что где-то подвох, нельзя просить ~ €100 за то, что есть бесплатно (IDE). Вот в Jetbrains продумали этот момент. Надеюсь в Eclipse меня услышат и подтянут этот момент. Morfi, спасибо за инфу.