1

我正在尝试获取具有某列最大值的行。通常我会为此使用 Rank 并选择 rank = 1 但是当我知道我只需要一列的最大值时这似乎毫无意义。这是我的 SQL:

SELECT
  name,
  value,
  MAX(version)
FROM
  my_table t
WHERE
  person_type = "STUDENT"
GROUP by NAME,VALUE
HAVING version = max(version)

这会在尝试运行时返回“您做错了涉及分组错误”,即“不是 GROUP BY 表达式”。如果我按字段将版本添加到组中,则此 SQL 会运行,但它显然会返回所有行,而不仅仅是每个行的最大版本。

所以我的问题主要是“为什么这不起作用?” 我正在选择版本的最大值,所以我不明白为什么我需要按它分组。我知道还有其他解决方案(分区,排名......),但我更感兴趣的是为什么这在语法上特别有缺陷。

编辑:更明确地使用这个有子句。

假设表 t 中有这两行:

NAME    VALUE    VERSION
JEREMY  C        1
JEREMY  A        2

此查询返回的内容应该是:

JEREMY A 2

但是,如果我删除了,那么我会得到:

JEREMY A 2
JEREMY C 2
4

4 回答 4

2

HAVING 子句通常需要包含由 group by 生成的列。实际上,您可以将 HAVING 子句视为 group by 上的 WHERE。

也就是说,查询:

select <whatever>
from t
group by <whatever>
having <some condition>

相当于:

select <whatever>
from (select <whatever>
      from t
      group by <whatever
     ) t
where <some condition>

如果你这样想,你会意识到 max(version) 是有意义的,因为它是一个聚合值。但是,“版本”没有意义,因为它既不是计算值也不是按列分组。

你似乎知道如何解决这个问题。另一条评论是某些数据库(尤其是 mysql)会接受您的语法。他们将“HAVING version = max(version)”视为“HAVING any(version) = max(version)”。

于 2012-06-20T19:27:38.653 回答
1

您正在尝试version在 HAVING 子句中使用,但它没有被分组。

如果您只需要名称、值和最大版本,则根本不需要该HAVING子句。

SELECT
  name,
  value,
  MAX(version)
FROM
  my_table t
WHERE
  person_type = "STUDENT"
GROUP by NAME,VALUE

HAVING 子句适用于您希望在聚合后拥有“Where”子句时,例如

HAVING max(version) > 5

编辑:

根据您的示例数据,您按 VALUE 进行分组,但您真正想要做的是确定每个 NAME 具有 MAX(VERSION) 的 VALUE。

为此,您需要使用 WHERE EXISTS 或自连接,如下所示:

select name, value, version from t 
where exists
(
  select 1 from
  (select name, max(version) version
     from t 
    group by name) s
  where s.name = t.name and s.version = t.version
)
于 2012-06-20T19:24:51.687 回答
1

此 SQL 语句失败,因为HAVING子句在GROUP BY-- 它之后运行,它只能对子句中列出的聚合或列进行操作GROUP BY。如果您仅按NAMEand分组VALUE,则单独没有任何意义 - 此时,对于andVERSION的每个组合,它都有许多可能的值,因此将它与每个and恰好具有 1 值的任何其他聚合进行比较是没有意义的一对。NAMEVALUEMAX(version)NAMEVALUE

于 2012-06-20T19:28:00.357 回答
0

另一种获得你想要的东西的方法:

select *
from (select name
        , value
        , version
        , max(version) over 
            (partition by name) as max_version
    from t)
where version = max_version;

示例执行: SQL> create table t (name varchar2(30) 2 , value varchar2(1) 3 , version number not null 4 , constraint t_pk primary key (name, version));

Table created.

SQL> insert into t select 'JEREMY', 'C', 1 from dual
  2  union all select 'JEREMY', 'A', 2 from dual
  3  union all select 'SARAH', 'D', 2 from dual
  4  union all select 'SARAH', 'X', 1 from dual;

4 rows created.

SQL> commit;

Commit complete.

SQL> select name, value, version
  2  from (select name
  3          , value
  4          , version
  5          , max(version) over
  6              (partition by name) as max_version
  7      from t)
  8  where version = max_version;

NAME                           V    VERSION
------------------------------ - ----------
JEREMY                         A          2
SARAH                          D          2
于 2012-06-20T20:33:56.770 回答