2017-06-15 131 views
1

我將我們的MySQL數據庫從5.6升級到5.7,並且正在修復一些引發一些錯誤的查詢。我正在工作的一個查詢涉及GROUP BY和COALESCE。MySQL 5.7 | GROUP BY |非聚合列錯誤

這裏是工作的查詢(抽象):

SELECT 
    MAX(a.id), 
    a.entered, 
    count(*) AS teh_count 
FROM 
    a 
INNER JOIN 
    b ON b.id = a.link_to_b_id 
INNER JOIN 
    c ON c.link_to_b_id = b.id 
WHERE 
    b.revision_id > 0 
AND 
    c.terminated_at = '0000-00-00 00:00:00' 
AND 
    a.created_at > date_sub(NOW(), INTERVAL 8 HOUR) 
GROUP BY 
    a.entered 
ORDER BY 
    teh_count DESC 
LIMIT 
    6; 

但我需要合併與c.override a.entered,所以我嘗試了以下內容:

SELECT 
    MAX(a.id), 
    a.entered, 
    COALESCE(c.override, a.entered) AS appearance, 
    count(*) AS teh_count 
FROM 
    a 
INNER JOIN 
    b ON b.id = a.link_to_b_id 
INNER JOIN 
    c ON c.link_link_to_b_id = b.id 
WHERE 
    b.revision_id > 0 
AND 
    c.terminated_at = '0000-00-00 00:00:00' 
AND 
    a.created_at > date_sub(NOW(), INTERVAL 8 HOUR) 
GROUP BY 
    a.entered 
ORDER BY 
    teh_count DESC 
LIMIT 
    6; 

然而MySQL 5.7現在拋出以下錯誤:Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'st_core.tuc.code_appearance_override' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

我假設我可以更改sql_mode,但我不想更改。錯誤告訴我的是合理的,因爲COALESCE列沒有彙總,所以作爲一個測試,我用MAX包裝了它,它工作正常,但是對我來說似乎有點不好意思。

有沒有更優雅的解決方案?

+0

此[在手冊中](https://dev.mysql.com/doc/refman/5.7/en/upgrading-from-previous-series.html)可能比粗略瀏覽更有價值 – RiggsFolly

+1

字段出現在「GROUP BY」子句中可確定記錄如何組合在一起。在你的案例中,記錄按「輸入」字段分組。因此,屬於同一組的所有記錄共享一個共同的「輸入」值。現在,這些記錄可能具有*不同的「覆蓋」值。 –

+0

...但你得到*只有一個*記錄返回每組'輸入的值。如果您還想要返回非聚合字段'override',則必須以某種方式選擇該字段在每個組中具有的其中一個值。 MAX是這樣做的一種方式。 –

回答

1

您還應該在您的group by條款中包含a.entered,這就是錯誤所說的。雖然不知道爲什麼你是由不同的列a.code_entered分組?

您的查詢應該像

SELECT 
    MAX(a.id), 
    a.entered, 
    COALESCE(c.override, a.entered) AS appearance, 
    count(*) AS teh_count 
FROM 
    a 
INNER JOIN 
    b ON b.id = a.link_to_b_id 
INNER JOIN 
    c ON c.link_link_to_b_id = b.id 
WHERE 
    b.revision_id > 0 
AND 
    c.terminated_at = '0000-00-00 00:00:00' 
AND 
    a.created_at > date_sub(NOW(), INTERVAL 8 HOUR) 
GROUP BY 
    a.entered, 
    COALESCE(c.override, a.entered) 
ORDER BY 
    teh_count DESC 
LIMIT 
    6; 
+0

我的歉意,'code_entered'應該是'輸入的',我忘了糾正作爲發佈到SO進程的抽象的一部分。 –

+0

Ahhh好吧,所以我必須在group by子句中複製COALESCE? –

+1

@MikePurcell,絕對是。你可以使用別名,但我更喜歡使用整個表達式 – Rahul

2

我想你想是這樣的:

SELECT MAX(a.id), 
     COALESCE(c.override, a.entered) AS appearance, 
     count(*) AS the_count 
FROM a INNER JOIN 
    b 
    ON b.id = a.link_to_b_id INNER JOIN 
    c 
    ON c.link_link_to_b_id = b.id 
WHERE b.revision_id > 0 AND 
     c.terminated_at = '0000-00-00 00:00:00' AND 
     a.created_at > date_sub(NOW(), INTERVAL 8 HOUR) 
GROUP BY appearance 
ORDER BY the_count DESC 
LIMIT 6; 

這從SELECT列表中刪除a.entered所以只有一個分組列。該列可以通過GROUP BY中的表別名引用。

+0

這工作,這讓我感到吃驚。出於某種原因,我認爲我無法在group by子句中使用派生值。謝謝。 –

+0

@MikePurcell。 。 。在一些數據庫中你可以(MySQL和Postgres)。大多數人不能。 –

+0

實際上,隨着@Rahul的回答,儘管我們不會很快改用oracle,但我會盡可能地堅持預定的標準。 +1的響應,因爲它的工作。謝謝。 –