Quando si utilizza GROUP BY, è possibile utilizzare le espressioni nell'elenco di selezione solo se hanno un unico valore per gruppo. Altrimenti ottieni risultati di query ambigui.
Nel tuo caso, MySQL ritiene che s.status
potrebbe avere più valori per gruppo. Ad esempio, stai raggruppando per p.products_id
ma s.status
è una colonna in un'altra tabella specials
, forse in una relazione uno-a-molti con la tabella products
. Quindi potrebbero esserci più righe in specials
con lo stesso products_id
, ma valori diversi per status
. In tal caso, quale valore per status
la query dovrebbe usare? È ambiguo.
Nei tuoi dati, potresti limitare le righe in modo tale da avere solo una riga in specials
per ogni riga in products
. Ma MySQL non può fare questa ipotesi.
MySQL 5.6 e versioni precedenti ti consentono di scrivere query così ambigue, confidando che tu sappia cosa stai facendo. Ma MySQL 5.7 consente un'applicazione più rigorosa per impostazione predefinita (questo può essere reso meno rigoroso per comportarsi come le versioni precedenti).
La soluzione è seguire questa regola:ogni colonna nell'elenco di selezione deve rientrare in uno dei tre casi seguenti:
- La colonna si trova all'interno di una funzione aggregata come COUNT(), SUM(), MIN, MAX(), AVERAGE() o GROUP_CONCAT().
- La colonna è una delle colonne denominate in
GROUP BY
clausola. - La colonna dipende funzionalmente dalle colonne citate in
GROUP BY
clausola.
Per ulteriori spiegazioni leggi questo eccellente blog:Debunking GROUP BY miti
Riguardo al tuo commento, posso solo fare un'ipotesi perché non hai pubblicato le definizioni delle tue tabelle.
Immagino che products_description
e manufacturers
sono funzionalmente dipendenti da products
, quindi va bene elencarli così come sono nell'elenco di selezione. Ma questa ipotesi potrebbe non essere corretta, non conosco il tuo schema.
Ad ogni modo, l'errore su s.status
dovrebbe essere risolto utilizzando una funzione di aggregazione. Sto usando MAX()
come esempio.
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;
Ho anche riscritto i tuoi join nel modo corretto. I join in stile virgola dovrebbero essere evitati.