簡體   English   中英

Oracle SQL - 這個分組有什么問題?

[英]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子句中列出的聚合或列進行操作。 如果您只按NAMEVALUE分組,則VERSION本身沒有任何意義 - 它在此時為NAMEVALUE每個組合提供了許多可能的值,因此將它與MAX(version)或任何其他組合進行比較沒有意義對於每個NAMEVALUE對,只有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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM