簡體   English   中英

分組時打印哪一列找到具有相同值的多行?

[英]Which column is printed when grouping by finds multiple rows with same value?

在此處輸入圖片說明

所以我的問題是,如果我在這個結果集上按 ContacType 分組,我將得到 3 行,一個用於 TMV,一個用於 TEL,另一個用於 EML,但是如果我打印 ContactValue 列,哪一個將打印用於 TMV 和 TEL? 是每個人第一次出現嗎?342222 和 33333?還是分組時有特定的順序?

為了使您所描述的查詢成為有效的 ANSI SQL,您必須指定一個要用於ContactValue列的聚合函數。 例如,如果您想要每種類型按字母順序排列的最早聯系人值,您可以編寫:

SELECT
    ContactType,
    MIN(ContactValue) AS ContactValueFirst
FROM yourTable
GROUP BY
    ContactType;

MySQL 的獨特之處在於它有一個名為ONLY_FULL_GROUP_BY的服務器模式,當禁用時,它實際上允許以下查詢:

SELECT
    ContactType,
    ContactValue
FROM yourTable
GROUP BY
    ContactType;

您的實際問題可能是在這種情況下會返回哪個聯系人值。 最佳實踐是甚至不要依賴這個服務器模式漏洞,而是始終按照我給出的第一個方法使用查詢。 一個主要原因是,如果您編寫代碼時假設ONLY_FULL_GROUP_BY模式被禁用,如果該模式被啟用,您現有的代碼可能會中斷。

來自ONLY_FULL_GROUP_BY模式的 文檔

如果 ONLY_FULL_GROUP_BY 被禁用……服務器可以自由地從每個組中選擇任何值,所以除非它們相同,否則選擇的值是不確定的,這可能不是你想要的。 此外,添加 ORDER BY 子句不會影響從每個組中選擇值。

您不應運行產生不確定結果的查詢。 如果這樣做,您可能會在代碼中產生錯誤。

實際上,當您執行像您顯示的查詢時,當前版本的 MySQL 會返回按索引順序讀取的第一個值。 返回的值取決於查詢使用的索引。 這可能會發生變化,具體取決於您從表中添加或刪除哪些索引,或者它可能會根據優化器選擇讀取哪個索引而發生變化。

MySQL 的未來版本可能會更改實現。 他們沒有義務保留非標准行為。 所以如果你試圖依賴這個“特性”,如果你升級了你的 MySQL 版本,你會得到一個驚喜。 它可能會導致您的應用程序中出現難以檢測的錯誤。

此外,不同的 SQL 數據庫實現可能會有不同的行為方式。 例如,SQLite 是我所知道的唯一允許此類模糊查詢的其他數據庫,但 SQLite 返回按索引順序讀取的最后一個值。 為什么? 只是因為他們實施它的方式。 無論如何,這是非標准和任意的行為,因此不能稱為錯誤。

這就是為什么創建具有此類可變結果的查詢是一個壞主意的原因。 它可能會導致令人困惑的應用程序行為。

在所有其他流行的 SQL 數據庫(PostgreSQL、Oracle、Microsoft 等)中,運行此類查詢只是一個錯誤。

這也是 ANSI SQL 規范中的一個錯誤。 ONLY_FULL_GROUP_BY被禁用時,MySQL 允許使用無效的 SQL。 你應該盡量避免它。


重新評論蒂姆的回答:

這里的想法是,實體 BBB 將具有優先權,所以按 ContactType 分組我首先想要 BBB 實體的所有聯系人,現在在這種情況下只有 AAA 有電子郵件(EML),所以我知道它會正常返回。 問題是您在兩個實體(BBB 和 AAA)中都有電話(TEL)和手機(TMV),但在這種情況下我需要 BBB。 那是我首先按 BBB 排序,然后按 AAA 排序,認為 Group By 將返回與 group by 列 (ContactType) 關聯的 ContactValue 的第一次出現。

這聽起來應該用窗口函數來解決,而不是 GROUP BY。 為此,您必須使用 MySQL 8.0 或更高版本。

WITH OrderedContacts AS (
  SELECT Entity, ContactType, ContactValue,
    ROW_NUMBER() OVER (PARTITION BY ContactType ORDER BY Entity DESC) AS rownum
  FROM Contacts
)
SELECT * FROM OrderedContacts WHERE rownum = 1

ORDER BY Entity DESC將 BBB 放在首位,如果給定聯系人類型存在 BBB。 然后是AAA。 所以如果有 BBB,它得到第 1 行。如果沒有 BBB,那么 AAA 得到第 1 行。這樣每個聯系人類型只返回一行,BBB 自然會獲得“優先級”。

如果您使用 min 或 max 作為聯系值,那么它將返回該聯系類型的最小值或最大值。

示例:在此將按聯系人類型升序排列

SELECT ContactType, MIN(ContactValue) AS ContactValueFirst FROM yourTable GROUP BY ContactType Order by 1

輸出:

Contacttype Contactvalue EML China@port.com TEL 914444444 TMV。 312222

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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