我正在尝试获取具有某些列的最大值的行。通常情况下,我会使用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
答案 0 :(得分:2)
HAVING子句通常需要包含由group生成的列。实际上,您可以将HAVING子句视为组中的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(版本)是有意义的,因为它是一个聚合值。但是,“版本”没有意义,因为它既不是计算值也不是按列分组。
你似乎知道如何解决这个问题。另一个评论是一些数据库(特别是mysql)会接受你的语法。他们将“HAVING version = max(version)”视为“HAVING any(version)= max(version)”。
答案 1 :(得分:1)
你试图在你的HAVING子句中使用version
,但它没有被分组。
如果您想要的只是名称,值和最大版本,则根本不需要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
)
答案 2 :(得分:1)
此SQL语句失败,因为HAVING
子句在GROUP BY
之后运行 - 它只能对GROUP BY
子句中列出的聚合或列进行操作。如果您仅按NAME
和VALUE
分组,VERSION
单独没有意义 - 它对NAME
和VALUE
的每个组合都有许多可能的值这一点因此将它与MAX(version)
或任何其他对NAME
和VALUE
对只有1个值的聚合进行比较是没有意义的。
答案 3 :(得分:0)
获得你想要的另一种方式:
select *
from (select name
, value
, version
, max(version) over
(partition by name) as max_version
from t)
where version = max_version;
示例执行: SQL&GT;创建表t(名称varchar2(30) 2,值varchar2(1) 3,版本号不为空 4,约束t_pk主键(名称,版本));
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