在MySQL中使用GROUP BY两次

时间:2012-06-21 19:36:53

标签: mysql sql

我的表看起来像这样。

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

有没有办法合并两个命令?

[编辑:澄清] 结果不应包含具有相同值的两个Head或具有相同值的两个Id。 删除这些重复项时,应保留IntTime最小的行。

5 个答案:

答案 0 :(得分:5)

此查询会返回您要查找的确切最终结果(example):

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和相应的IdMIN(intTime)。缩小后,最终查询将返回所有行。您可以将最终(最外面)查询视为仅包含所需行的表的查询,因此您可以进行其他比较(例如WHERE final.intTime > 3)。

答案 1 :(得分: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

答案 2 :(得分:1)

如果我理解正确,你需要head和id具有最小int / time值的行。我没有看到第二个“头脑组”是什么让你。

以下是我认为你想要的:

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

您可能只想要所有“head”值的最小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

答案 3 :(得分:0)

例如,我不确定您的样本结果如何到达Location = 7 for ARMY。试试这个......

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

答案 4 :(得分:0)

使用UNION语法?

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