2012-02-15 132 views
2

如果我有一个数据表编号:SQL GROUP BY与集合

+------+------+------+------+ 
| colA | colB | colC | colD | 
+------+------+------+------+ 
| 1 | 2 | 3 | 4 | 
| 1 | 2 | 9 | 5 | 
+------+------+------+------+ 

做:

select colA, colB, colC, MAX(colD) FROM Numbers GROUP BY colA, colB; 

我认为,它应该由colA, colB返回行2.群体,并挑选最大的一个在colD

不幸的是,这不起作用,因为您还必须由colC进行分组才能返回。

为什么?有没有另一种方法来做我想做的事情?

我想要colAcolB中相同的行,但是最大的一个在colD

回答

5

有几种方法可以解决这个问题。也许最简单的是JOIN针对一个子查询,该子查询执行colA, colB组,并从中找到完整对应的行。

SELECT 
    tbl.colA, 
    tbl.colB, 
    tbl.colC, 
    tbl.colD 
FROM tbl JOIN (
    SELECT 
    colA, 
    colB, 
    MAX(colD) AS maxD 
    FROM tbl 
    GROUP BY colA, colB 
) g ON tbl.colA = g.colA AND tbl.colB = g.colB AND tbl.colD = g.maxD 
+0

这对于NATURAL JOIN来说是一个很好的用例。 – Benoit 2012-02-15 13:59:05

+0

谢谢,并且非常感谢Benoit对这个问题进行了重构:)如果两个列名都相同,那么是否真的必须命名所有“on”:s? – momomo 2012-02-15 14:11:55

+0

@Hamidam是的,只要其中一个不是主键,你确实需要所有列在'ON'子句中的。例如,如果'colA'是一个唯一的键值,那么你可以'ON tbl.colA = g.colA',但由于你的属性并不唯一,所以你需要组合必要的列数来创建一个唯一的值colA ,colB,MAX(colD)' – 2012-02-15 14:19:37

0

您的查询的问题之一是,您想要显示codC的值,但它不在组中。要显示没有聚合函数的值,它必须位于组中。因此,要解决您的查询,你可以做这样的事情:

select n1.* from Number n1 
inner join (select colA, colB, max(colD) as colD from Number GROUP BY colA, colB) n2 on n1.colA = n2.colA and n1.colB = n2.colB and n1.colD = n2.colD 

会以选择的最大(冷)每个可乐COLB所有行。

+2

如果您没有将'max(colD)'别名作为colD,将无法使用! – Benoit 2012-02-15 13:33:28

+0

@Benoit谢谢:) – 2012-02-15 13:35:47

3

你可以这样做:

SELECT N1.colA, N1.colB, N1.colC, N1.colD 
    FROM Numbers N1 
    LEFT JOIN Numbers N2 ON N2.colA = N1.colA 
         AND N2.colB = N1.colB 
         AND N2.colD > N1.colD 
    WHERE N2.colA IS NULL; 

的LEFT JOIN将查找在与同列A和B,以及更大的列D.同一表中的行如果发现任何行,那么你已经在在列最大值D.

这在技术上是一样的:

SELECT * 
    FROM Numbers N 
WHERE NOT EXISTS 
    (SELECT NULL /* or whatever you want, doesn't matter */ 
     FROM Numbers 
     WHERE colA = N.colA 
      AND colB = N.colB 
      AND colD > N.colD 
    ) 

请注意,您可能要添加一个DISTINCT如果返回欺骗行。