Использование 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