11

我的桌子:

ID   NUM   VAL
1    1     Hello
1    2     Goodbye
2    2     Hey
2    4     What's up?
3    5     See you

如果我想返回每个 ID 的最大数量,那真的很干净:

SELECT MAX(NUM) FROM table GROUP BY (ID)

但是,如果我想获取与每个 ID 的每个数字的最大值相关的值怎么办?

为什么我不能这样做:

SELECT MAX(NUM) OVER (ORDER BY NUM) FROM table GROUP BY (ID) 

为什么这是一个错误?我希望这个选择按 ID 分组,而不是为每个窗口单独分区......

编辑:错误是“不是 GROUP BY 表达式”。

4

3 回答 3

16

您可能可以使用该MAX() KEEP(DENSE_RANK LAST...)功能:

with sample_data as (
  select 1 id, 1 num, 'Hello' val from dual union all
  select 1 id, 2 num, 'Goodbye' val from dual union all
  select 2 id, 2 num, 'Hey' val from dual union all
  select 2 id, 4 num, 'What''s up?' val from dual union all
  select 3 id, 5 num, 'See you' val from dual)
select id, max(num), max(val) keep (dense_rank last order by num)
from sample_data
group by id;
于 2012-04-27T23:20:45.277 回答
4

当您使用窗口功能时,您不再需要使用 GROUP BY,这就足够了:

select id, 
     max(num) over(partition by id) 
from x 

实际上,您可以在不使用窗口函数的情况下获得结果:

select * 
from x
where (id,num) in
  (
     select id, max(num) 
     from x 
     group by id
  )

输出:

ID  NUM VAL
1   2   Goodbye
2   4   What's up
3   5   SEE YOU

http://www.sqlfiddle.com/#!4/a9a07/7


如果你想使用窗口功能,你可以这样做:

select id, val, 
     case when num =  max(num) over(partition by id) then
        1
     else
        0
     end as to_select
from x 
where to_select = 1

或这个:

select id, val 
from x 
where num =  max(num) over(partition by id) 

但由于不允许这样做,你必须这样做:

with list as
(
  select id, val, 
     case when num =  max(num) over(partition by id) then
        1
     else
        0
     end as to_select
  from x
)
select * 
from list 
where to_select = 1

http://www.sqlfiddle.com/#!4/a9a07/19

于 2012-04-27T23:33:17.217 回答
3

如果您正在寻找包含来自的值的MAX(num) GROUP BY id,这往往是一种常见的模式......

WITH
  sequenced_data
AS
(
  SELECT
    ROW_NUMBER() OVER (PARTITION BY id ORDER BY num DESC) AS sequence_id,
    *
  FROM
    yourTable
)
SELECT
  *
FROM
  sequenced_data
WHERE
  sequence_id = 1


编辑

我不知道 TeraData 是否会允许这样做,但逻辑似乎是有道理的......

SELECT
  *
FROM
  yourTable
WHERE
  num = MAX(num) OVER (PARTITION BY id)

或者可能...

SELECT
  *
FROM
(
  SELECT
    *,
    MAX(num) OVER (PARTITION BY id) AS max_num_by_id
  FROM
    yourTable
)
  AS sub_query
WHERE
  num = max_num_by_id 

这与我之前的回答略有不同;如果多条记录与相同的MAX(num),这将返回所有记录,另一个答案将只返回一个。


编辑

在您提出的 SQL 中,错误与该OVER()子句包含不在您的 GROUP BY 中的字段这一事实有关。这就像尝试这样做...

SELECT id, num FROM yourTable GROUP BY id

num是无效的,因为该字段中可以有多个值返回的每一行(返回的行由 定义GROUP BY id

同理,你不能放在子句num里面。OVER()

SELECT

  id,

  MAX(num),                <-- Valid as it is an aggregate

  MAX(num)                 <-- still valid
  OVER(PARTITION BY id),   <-- Also valid, as id is in the GROUP BY

  MAX(num)                 <-- still valid
  OVER(PARTITION BY num)   <-- Not valid, as num is not in the GROUP BY

FROM
  yourTable
GROUP BY
  id


当您无法在OVER()子句中指定某些内容时,请参阅此问题,以及显示何时(我认为)可以的答案:over-partition-by-question

于 2012-04-27T23:23:53.977 回答