MySQL, GroupBy OrderBy - PullRequest
       44

MySQL, GroupBy OrderBy

4 голосов
/ 22 февраля 2012

Первый вопрос, который вы, вероятно, задаете: сколько групп по порядку / по порядку существует на SO?Много.Ничто из этого не соответствует моим конкретным обстоятельствам.Вот мой следующий SQL-запрос.

Цель состоит в том, чтобы получить последние носители для каждой команды в $teamArr (набор уникальных идентификаторов).

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

Вот команда MySQL (с помощью команды PHP sprintf() для простотыиспользовать с идентификаторами команды).

sprintf("SELECT M.*, T.name, T.has_image
    FROM media AS M
        JOIN teams AS T
          ON T.team_uid = M.team_uid
    WHERE M.team_uid IN (%s)
    GROUP BY T.team_uid
    ORDER BY M.time DESC", implode(", ", $teamArr));

Сценарий:

команда A имеет элемент мультимедиа 3 часа назад, команда B имеет 2 элемента 6 часов назад и 2 дня назад, и командаC имеет медиа-элемент 9 часов назад.

Если порядок выбора оказывается Командой A, C, B, медиа-элементы будут выглядеть следующим образом ...

  • MediaA 3 часа назад медиа-элемент
  • TeamC 9 часов назад медиа-элемент
  • TeamB 2 дня назад медиа-элемент

Вероятно, будут некоторые глупые замечания, говорящие

Просто заказывай по названию команды манекен!Такая простая проблема.(этот ответ наберет около +4 голосов)

Но это явно не помогает мне.Я не могу знать, какие команды будут иметь оптимальный порядок (если какой-либо естественный или неестественный порядок будет работать даже с более чем 3 случаями).Есть ли такой способ, которым я могу сделать это в 1 запросе SQL.Я слышал, что MySQL в цикле - плохое решение, поэтому я хочу, чтобы это работало в 1 вызове SQL.

1 Ответ

6 голосов
/ 22 февраля 2012

Этот тип запроса обычно помечается как «наибольший по количеству групп» для дальнейшего использования.

Требуется максимальное время для каждой команды и соответствующих столбцов, верно?

Типичным способом решения этой проблемы является LEFT JOIN таблица, которую вы хотите получить максимально для себя (в вашем случае media):

SELECT M.*, T.name, T.has_image
FROM media AS M
LEFT JOIN media AS M2              -- new: join media to itself
       ON M.team_uid = M2.team_uid -- within each team_uid (GROUP BY var)
      AND M.time < M2.time         -- and a sort on time (ORDER BY var)
JOIN teams AS T              -- same as before.
 ON T.team_uid = M.team_uid
WHERE M.team_uid IN (%s)     
  AND M2.time IS NULL        -- new: this selects the MAX M.time for each team.

Изменения:

  • LEFT JOIN media на себя в каждый team_uid (переменная GROUP BY) и такой, что M.time < M2.time (переменная, которую мы хотим получить МАКС).
  • , поскольку это LEFT JOIN, если есть M.time, для которого не больше M2.time (для той же команды), то M2.time будет NULL.Это именно то время, когда M.time является максимальным временем для этой команды.
  • добавьте M2.time IS NULL в WHERE условие (для обеспечения выполнения вышеприведенного)
  • уберите GROUP BY,ORDER BY (рассматривается в условии соединения).
...