Использование GROUP BY дважды в MySQL

Мой стол выглядит так.

Location    Head    Id  IntTime
1           AMD     1   1
2           INTC    3   3
3           AMD     2   2
4           INTC    4   4
5           AMD2    1   0
6           ARMH    5   1
7           ARMH    5   0
8           ARMH    6   1
9           AAPL    7   0
10          AAPL    7   1

Местоположение является первичным ключом. Мне нужно GROUP BY Head и Id, и когда я использую GROUP BY, мне нужно сохранить строку с наименьшим IntTime.

После первого идентификатора GROUP BY Id я должен получить (я оставляю самый маленький IntTime)

Location    Head    Id  IntTime
2           INTC    3   3
3           AMD     2   2
4           INTC    4   4
5           AMD2    1   0
7           ARMH    5   0
8           ARMH    6   1
9           AAPL    7   0

После второго GROUP BY Head я должен получить (у меня самый маленький IntTime)

Location    Head    Id  IntTime
2           INTC    3   3
3           AMD     2   2
5           AMD2    1   0
7           ARMH    5   0
9           AAPL    7   0

Когда я запускаю следующую команду, я сохраняю наименьшее значение IntTime, но строки не сохраняются.

SELECT Location, Head, Id, MIN(IntTime) FROM test 
GROUP BY Id

Кроме того, чтобы запустить второй GROUP BY, я сохраняю эту таблицу и делаю снова

SELECT Location, Head, Id, MIN(IntTime) FROM test2 
GROUP BY Head

Есть ли способ объединить обе команды?

[Редактировать: уточнение] Результат не должен содержать двух заголовков с одинаковым значением или двух идентификаторов с одинаковым значением. При удалении этих дубликатов строка с наименьшим IntTime должна сохраняться.

5 ответов

Решение

Этот запрос возвращает точные конечные результаты, которые вы ищете ( пример):

SELECT `final`.*
FROM `tableName` AS `final`
JOIN (
    SELECT `thead`.`Id`, `Head`, MIN(`intTime`) AS `min_intTime`
    FROM `tableName` AS `thead`
    JOIN (
        SELECT `Id`, MIN(intTime) as min_intTime
        FROM `tableName` AS `tid`
        GROUP BY `Id`
    ) `tid`
    ON `tid`.`Id` = `thead`.`Id`
    AND `tid`.`min_intTime` = `thead`.`intTime`
    GROUP BY `Head`
) `thead`
ON `thead`.`Head` = `final`.`Head`
AND `thead`.`min_intTime` = `final`.`intTime`
AND `thead`.`Id` = `final`.`Id`

Как это устроено

Самые внутренние группы запросов по Idи возвращает Id и соответствующий MIN(intTime), Затем средний запрос группируется по Headи возвращает Head и соответствующий Id а также MIN(intTime), Последний запрос возвращает все строки после сужения. Вы можете думать о конечном (самом внешнем) запросе как о запросе к таблице только с теми строками, которые вам нужны, поэтому вы можете выполнять дополнительные сравнения (например, WHERE final.intTime > 3).

SELECT a.*
FROM test a
NATURAL JOIN
(
    SELECT c.Head, c.Id, MIN(c.IntTime) AS IntTime
    FROM test c
    NATURAL JOIN
    (
        SELECT Id, MIN(IntTime) AS IntTime
        FROM test
        GROUP BY Id
    ) d
    GROUP BY c.Head
) b
ORDER BY a.Location

Если я правильно понимаю, вы хотите строки с наименьшими значениями int/time по head и id. Я не вижу, что получает вторая "группа за головой".

Следующее делает то, что я думаю, что вы хотите:

select t.*
from t join
     (select head, id, min(intTime) as min_intTime
      from t
      group by head, id
     ) tsum
     on tsum.head = t.head and
        tsum.id = t.id and
        tsum.min_intTime = t.intTime

Возможно, вы просто захотите наименьшее значение intTime для всех "головных" значений. Если это так, запрос выглядит так:

select t.*
from t join
     (select head, min(intTime) as min_intTime
      from t
      group by head
     ) tsum
     on tsum.head = t.head and
        tsum.min_intTime = t.intTime

Использовать синтаксис UNION?

(SELECT Location, Head, Id, MIN(IntTime) FROM test 
GROUP BY Id)
UNION
(SELECT Location, Head, Id, MIN(IntTime) FROM test2 
GROUP BY Head)

Я не уверен, как, например, ваш результат выборки достиг местоположения = 7 для ARMH. Попробуй это...

SELECT MIN(Location), Head, Id, MIN(IntTime)
FROM test
GROUP BY Head, Id
Другие вопросы по тегам