Korzystając z funkcji GROUP BY, można używać wyrażeń z listy wyboru tylko wtedy, gdy mają one jedną wartość na grupę. W przeciwnym razie otrzymasz niejednoznaczne wyniki zapytania.
W twoim przypadku MySQL uważa, że s.status
może mieć wiele wartości na grupę. Na przykład grupujesz według p.products_id
ale s.status
jest kolumną w innej tabeli specials
, być może w relacji jeden-do-wielu z tabelą products
. Więc może być wiele wierszy w specials
z tym samym products_id
, ale inne wartości dla status
. Jeśli tak jest, jaka wartość dla status
należy użyć zapytania? To niejednoznaczne.
W swoich danych może się zdarzyć, że ograniczysz wiersze tak, że masz tylko jeden wiersz w specials
dla każdego wiersza w products
. Ale MySQL nie może przyjąć takiego założenia.
MySQL 5.6 i wcześniejsze pozwalają pisać takie niejednoznaczne zapytania, ufając, że wiesz, co robisz. Ale MySQL 5.7 domyślnie umożliwia bardziej rygorystyczne egzekwowanie (może to być mniej rygorystyczne, aby zachowywać się jak wcześniejsze wersje).
Rozwiązaniem jest przestrzeganie tej zasady:każda kolumna na liście wyboru musi należeć do jednego z trzech przypadków:
- Kolumna znajduje się wewnątrz funkcji agregującej, takiej jak COUNT(), SUM(), MIN, MAX(), AVERAGE() lub GROUP_CONCAT().
- Kolumna jest jedną z kolumn nazwanych w
GROUP BY
klauzula. - Kolumna jest funkcjonalnie zależna od kolumn nazwanych w
GROUP BY
klauzula.
Aby uzyskać więcej wyjaśnień, przeczytaj ten wspaniały blog:Obalanie GROUP BY mity
Odnieś się do twojego komentarza, mogę tylko zgadywać, ponieważ nie opublikowałeś definicji tabeli.
Domyślam się, że products_description
i manufacturers
są funkcjonalnie zależne od products
, więc można je wymienić tak, jak na liście wyboru. Ale to założenie może nie być poprawne, nie znam twojego schematu.
W każdym razie błąd dotyczący s.status
należy rozwiązać za pomocą funkcji agregującej. Używam MAX()
jako przykład.
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;
Przepisałem również twoje złączenia we właściwy sposób. Należy unikać złączeń w stylu przecinków.