[英]Oracle SQL — What's wrong with this grouping?
我試圖抓住一行有一些列的最大值。 通常情況下,我會使用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會運行,但它顯然會返回所有行,而不僅僅是每個行的最大版本。
所以我的問題主要是“為什么這不起作用?” 我正在選擇版本的最大值,所以我不明白為什么我需要按它分組。 我知道還有其他解決方案(分區,排名......)但我更感興趣的是為什么這在語法上有缺陷。
編輯:更明確地使用此having子句。
假設表t中有這兩行:
NAME VALUE VERSION
JEREMY C 1
JEREMY A 2
從此查詢返回的內容應為:
JEREMY A 2
但如果我刪除,那么我會得到:
JEREMY A 2
JEREMY C 2
通常,HAVING子句需要包含由group by生成的列。 實際上,您可以將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)”。
你試圖在你的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
)
此SQL語句失敗,因為HAVING
子句在GROUP BY
之后運行 - 它只能對GROUP BY
子句中列出的聚合或列進行操作。 如果您只按NAME
和VALUE
分組,則VERSION
本身沒有任何意義 - 它在此時為NAME
和VALUE
每個組合提供了許多可能的值,因此將它與MAX(version)
或任何其他組合進行比較沒有意義對於每個NAME
和VALUE
對,只有1個值的聚合。
得到你想要的另一種方式:
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(名稱varchar2(30)2,值varchar2(1)3,版本號不為null 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.