如何在Oracle中按一个字段分组?

时间:2016-05-27 22:12:03

标签: sql oracle group-by

假设我有这样的数据集:

MANAGER  |  USER  |  NUM1  |  NUM2  |  NUM3
---------|--------|--------|--------|-------
Bob      |  Jane  |  9     |  88    |  2
Bob      |  Jane  |  34    |  32    |  52
Bob      |  Jane  |  32    |  111   |  9
Bob      |  Rick  |  64    |  1     |  102
Bob      |  Rick  |  12    |  41    |  16
Bob      |  Rick  |  4     |  13    |  20
Bob      |  Mark  |  87    |  1     |  333
Bob      |  Mark  |  342   |  41    |  16
Bob      |  Mark  |  54    |  813   |  6

正如您所看到的数字列不同,管理器始终相同,并且用户正在重复。

我想按用户分组,以便每个用户只显示一列。

所以最终的数据集看起来像这样:

MANAGER  |  USER  |  NUM1  |  NUM2  |  NUM3
---------|--------|--------|--------|-------
Bob      |  Jane  |  9     |  88    |  2
Bob      |  Rick  |  64    |  1     |  102
Bob      |  Mark  |  87    |  1     |  333

我想运行这样的东西:

SELECT MANAGER, USER, NUM1, NUM2, SUM(NUM3) AS NUM3
FROM MYTABLE
GROUP BY USER

由于您需要按所有聚合函数进行分组,因此此代码无效。我不想在其他列上使用任何聚合函数,因为它们将更改NUM1和NUM2的值。有没有办法解决?任何人都知道我能做些什么来实现这一目标?

1 个答案:

答案 0 :(得分:2)

如果您确实需要在NUM3列上获得总和,那么这是一种可能的解决方案。使用SUM的分析版本(窗口函数)。这与ROW_NUMBER一起。这允许您定义每组的第一行,并仍然选择组的总和:

SELECT MANAGER, USER, NUM1, NUM2, NUM3
FROM
    (SELECT 
      MANAGER, USER, NUM1, NUM2, 
      ROW_NUMBER() over (partition by MANAGER, USER /* order by ....*/) AS USERROWNUMBER,
      SUM(NUM3) over (partition by MANAGER, USER) AS NUM3
    FROM MYTABLE)
WHERE
  USERROWNUMBER = 1

在ROW_NUMBER窗口函数中指定order by子句会很好,否则Oracle可能会选择任何顺序,甚至可能在不同的场合以不同的顺序返回行。按ID排序,或通过NUM1排序,有助于获得更一致的结果。

如果您不需要将NUM3相加,则可以选择NUM1和NUM2,并将整个SUM表达式保留在其中。