2016-08-01 69 views
1

我有一個問題,我的查詢和mysql引發以下錯誤:MySQL的錯誤:SELECT列表是不是在GROUP BY子句

#1055 - Expression #66 of SELECT list is not in GROUP BY clause and 
contains nonaggregated column 's.status' which is not functionally 
dependent on columns in GROUP BY clause; this is incompatible with 
sql_mode=only_full_group_by 

查詢:

select p.*, 
pd.*, 
m.*, 
IF(s.status, s.specials_new_products_price, null) as specials_new_products_price, 
IF(s.status, s.specials_new_products_price, p.products_price) as final_price 
FROM products p 
LEFT JOIN specials s ON p.products_id = s.products_id 
LEFT JOIN manufacturers m using(manufacturers_id) , 
      products_description pd, 
      categories c, 
      products_to_categories p2c 
WHERE p.products_view = 1 
AND p.products_status = 1 
AND p.products_archive = 0 
AND c.virtual_categories = 0 
AND p.products_id = pd.products_id 
AND p.products_id = p2c.products_id 
AND p2c.categories_id = c.categories_id 
AND pd.language_id = 1 

GROUP BY p.products_id; 

回答

11

當您使用GROUP BY ,只有在每個組有單個值時,纔可以在選擇列表中使用表達式。否則你會得到不明確的查詢結果。

就你而言,MySQL認爲s.status可能每組有多個值。例如,您正在按p.products_id分組,但s.status是另一個表specials中的一列,可能與表products處於一對多關係。因此,specials中可能有多個行,與​​相同,但status的值不同。如果是這樣的話,查詢使用status的哪個值?它含糊不清。

在您的數據中,您可能會碰巧限制行,因此products中的每行只有specials中的一行。但MySQL無法做出這樣的假設。

MySQL 5.6和更早的版本讓你編寫這樣的模糊查詢,相信你知道你在做什麼。但是MySQL 5.7默認實現更嚴格的執行(這可以不像以前的版本那樣嚴格)。

解決辦法是遵循這個規則:在你的選擇列表中的每一列必須分爲以下三種情況之一:

  • 列就像COUNT聚合函數內(),SUM(),MIN ,MAX(),AVERAGE()或GROUP_CONCAT()。
  • 該列是GROUP BY子句中指定的列之一。
  • 該列在功能上依賴於GROUP BY子句中指定的列。

更多解釋閱讀本優秀的博客:Debunking GROUP BY myths


回覆你的評論,我只能猜測,因爲你還沒有發佈你的表定義。

我猜products_descriptionmanufacturers在功能上依賴於products,所以可以將它們按原樣列在選擇列表中。但是這個假設可能不正確,我不知道你的模式。

無論如何,有關s.status的錯誤應通過使用聚合函數來解決。我以MAX()爲例。

SELECT p.*, 
pd.*, 
m.*, 
MAX(IF(s.status, s.specials_new_products_price, NULL)) 
    AS specials_new_products_price, 
MAX(IF(s.status, s.specials_new_products_price, p.products_price)) 
    AS final_price 
FROM products p 
LEFT OUTER JOIN specials s ON p.products_id = s.products_id 
INNER JOIN manufacturers m ON p.manufacturers_id = m.manufacturers_id 
INNER JOIN products_description pd ON p.products_id = pd.products_id 
INNER JOIN products_to_categories p2c ON p.products_id = p2c.products_id 
INNER JOIN categories c ON p2c.categories_id = c.categories_id 
WHERE p.products_view = 1 
AND p.products_status = 1 
AND p.products_archive = 0 
AND c.virtual_categories = 0 
AND pd.language_id = 1 
GROUP BY p.products_id; 

我也重寫了正確的方式加入。應避免逗號式連接。

+1

打我吧!很好的解釋。 –

+0

我試過不同的方式,像選擇SQL_CALC_FOUND_ROWS s.products_id,或選擇SQL_CALC_FOUND_ROWS計數(p.products_id),但沒有解決方案任何想法重寫這個? – kurama

+0

@ kurama您正在嘗試彙總您正在分組的列。正如Bill所描述的那樣,您需要確保選擇列表中包含的其他列包含「GROUP BY」子句,或者它們已經彙總,或者依賴於分組列,以便分組正常工作。例如,從產品p組中選擇p.products_id,s.status,sum(p.products_price),... p.products_id,s.status' –

1

您是否想做ORDER BYGROUP BY子句嘗試爲GROUP BY子句中列中的每個不同值返回一行,除非向該子句添加更多列。該錯誤正在拋出,因爲您有其他未彙總的列未包含在該子句中 - 彙總的列將類似於MAX(p.products_id)SUM(p.products_price)。在您的查詢中,有多個具有相同p.product_price和不同s.status值的行,因此GROUP BY無意義。

MySQL的分組方式處理:https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html 聚合函數:http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html

0

如果你想使用特定的列GROUP BY和得到的結果的ID的有一個好的技巧如何做到這一點:

SELECT `distinct_column`, MAX(`id`), MAX(`another_int_column`) FROM `table_name` GROUP BY `distinct_column` 

結果:

distinct_column id  another_int_column 
Abertamy   13579 11 
Adamov   17765 14 
Adolfovice  2924  3 
Achotín   2241  2 
Babice   17772 14 

現在,你必須從distinct_column和Wi不同的值它是相應行的值。

source

我認爲ID和another_int_column必須是唯一的,但我不知道。