2012-02-21 4 views
4

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

Цель состоит в том, чтобы получить последние средства массовой информации для каждой команды в $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)); 

Сценарий:

Команда А имеет медиа-элемент 3 часов назад, команда Б имеет 2 пунктов 6 часов назад и 2 дней назад, и команда С имеет медиа-элемент 9 часов назад.

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

  • TeamA в 3 часа назад элемента медиа
  • TeamC в 9 часов назад элемент медиа
  • TeamB в 2 дня назад пункт СМИ

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

Закажите только название команды dummy! Такая простая проблема. (этот ответ получит около +4 голосов)

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

+1

Нет, в SQL это не простая задача. Обычно это спрашивают. Обычно достаточно иметь собственный тег: ['[наибольший-n-per-group]'] (http://stackoverflow.com/questions/tagged/greatest-n-per-group). Поиск, нажав на этот тег выше или под заголовком ** Related **, справа. –

+0

вместо дней вы можете превратить 2 дня в 48 часов, чтобы вы использовали одинаковое сравнение для всех? – northpole

+0

его отметка времени unix @northpole. Поэтому сравнение не имеет значения ... Это просто сценарий, чтобы вы могли видеть, что происходит. – Michael

ответ

6

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

Вы хотите, чтобы максимальное количество членов команды и соответствовало колонкам, не так ли?

Типичный способ решения этой проблемы заключается в 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 JOINmedia к сам в пределах каждый team_uid (переменная GROUP BY), и такой, что M.time < M2.time (переменная, которую мы хотим MAX of).
  • , так как это LEFT JOIN, если есть M.time, для которого есть не более M2.time (для той же команды), то M2.time будет NULL. Именно тогда, когда M.time - это MAX время для этой команды.
  • добавить M2.time IS NULL в состоянии WHERE (для обеспечения выше)
  • удалить GROUP BY, ORDER BY (рассматривается в условии объединения).
+0

Позвольте мне попробовать. Я начал читать. Я никогда не слышал о проблеме «большая-на-группу», но теперь я могу хотя бы начать ее искать! – Michael

+0

Насколько я могу судить, это работает правильно. Я очень благодарен вам за код, но тем более за объяснение. Это делает кодирование лучше, если я понимаю аргументы за кодом! – Michael

+1

Не стоит беспокоиться - такой запрос запутан, когда вы это делаете сначала, но если вы попробуете только таблицу «media» (забудьте о присоединении в 'команды' на данный момент) и посмотрите таблицу соединений без каких-либо условий' WHERE' применяется, т. е. 'SELECT .., M.time, M2.time FROM M LEFT JOIN M2 ON..' * без *' IS NULL', он может быть довольно образованным. –

Смежные вопросы