Zitat von Meister1900
Beitrag anzeigen
- Zunächst muß man mal konstatieren, daß das eine ungeschickte Formulierung ist, korrekt hätte es besser heißen sollen "...all values in each nonaggregated column not named in the GROUP BY are the same within each group." Gut, so gut kann ich jetzt auch kein Englisch, daß ich beurteilen kann, ob dies von muttersprachlichen Englischsprechenden nicht ohnehin so verstanden werden würde.
- So oder so - die Aussage beschreibt zunächst einmal nur das, was den Unterschied macht und ist demnach (scheinbar) trivial: Sind nämlich die Werte derjenigen Spalte in der SELECT-Liste, die weder aggregiert wird noch im Group by steht, für eine einzelne Gruppe unterschiedlich, würde dies im Falle der Deaktivierung von ONLY_FULL_GROUP_BY und Beibehaltung der Gruppe (also ohne die "fragliche" Spalte) zu einer Mehrdeutigkeit der Auswahl für diese zusätzliche Spalte und damit zu einem zufälligen Ergebnis führen. Im Falle der Aufnahme der Spalte in die GROUP BY-Liste resultiert demgegenüber eine "Verfeinerung" der Gruppierung (im Sinne von einer größeren Anzahl von Gruppen mit weniger Mitgliedern), die auch nicht hilfreich ist.
- Nun folgt natürlich zwingend die absolut logische schlußfolgernde Frage: Wenn das ONLY_FULL_GROUP_BY nicht hilfreich ist, wann kann es denn dann überhaupt hilfreich sein, ist es damit nicht doch überflüssig?
- Um dies zu überprüfen, müssen wir uns die Doku nochmal genauer anschauen und dabei (leider für die, die dies nicht gerne tun ... ) ein wenig Lesearbeit investieren, hier erstmal der Link: https://dev.mysql.com/doc/refman/5.7...-handling.html
Dort wird ausführlich dargelegt, was MySQL mit Abfragen macht, die diese Problematik aufweisen, Stichwörter sind "funktionale Abhängigkeit" und "Eindeutigkeit". Und es wird deutlich: "Eigentlich" müssten doch alle Fälle, in denen die vorgenannte Konstellation so gegeben ist, daß eine Aufnahme der fraglichen Spalte in die SELECT-Liste unschädlich ist, erfaßt werden, da doch - wie dort ausgeführt - MySQL über die Befähigung zur Detektion solcher Fälle besitzt. Oder?
Tatsächlich beinhaltet das, was dort angeführt wird auch die Kehrseite als komplett logische Schlußfolgerung: Wenn MySQL "solche Fälle" entdecken kann und dann eine Diskrepanz zwischen SELECT- und GROUP BY-Liste auch bei aktiviertem ONLY_FULL_GROUP_BY geduldet wird, dann steht und fällt diese Option damit, daß dies "Befähigung" lückenlos funktioniert. Tatsächlich funktioniert sie nicht lückenlos, und deshalb ist die Deaktivierung von ONLY_FULL_GROUP_BY auch sinnvoll. - Und hier liegt dann auch die wirkliche Bedeutung des von Dir zitierten Satzes, die in 5 scheinbar harmlosen Wörtchen versteckt ist: " ... due to some property of the data ...". Was sollen das denn eigentlich für "gewisse Eigenschaften der Daten" sein, wo noch nicht einmal die Detektion funktionaler Abhängigkeiten und entsprechende "Tolerierung" (von "überschüssigen" SELECT-Spalten) hilft? Antwort ist: Das ist die falsche Frage, es ist nämlich nicht der Punkt, daß MySQL richtig arbeitet, wenn es die Abhängigkeit entdeckt, sondern: ob es die Abhängigkeit entdeckt. Wie unter 4. bereits geschrieben: Das ist nicht immer der Fall.
TEST-DATENBANK
Folgende Test-DB muß verwendet werden:
Code:
-- phpMyAdmin SQL Dump -- version 4.8.5 -- https://www.phpmyadmin.net/ -- -- Host: 127.0.0.1 -- Erstellungszeit: 17. Nov 2019 um 18:20 -- Server-Version: 10.1.38-MariaDB -- PHP-Version: 7.3.2 SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET AUTOCOMMIT = 0; START TRANSACTION; SET time_zone = "+00:00"; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8mb4 */; -- -- Datenbank: `groupby_ex` -- -- -------------------------------------------------------- -- -- Tabellenstruktur für Tabelle `tbl_abteilung` -- CREATE TABLE `tbl_abteilung` ( `AbteilungID` int(11) NOT NULL, `FilialeID_FK` int(11) NOT NULL, `AbteilungBez` text NOT NULL, `AbteilungLeiterMbID` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Daten für Tabelle `tbl_abteilung` -- INSERT INTO `tbl_abteilung` (`AbteilungID`, `FilialeID_FK`, `AbteilungBez`, `AbteilungLeiterMbID`) VALUES (1, 1, 'VerwaltungHH', 3), (2, 1, 'ProduktionHH', 9), (3, 1, 'VertriebHH', 5), (4, 1, 'ZentraleDV_HH', 6), (5, 2, 'VerwaltungM', 4), (6, 2, 'ProduktionM', 10), (7, 2, 'VertriebM', 7), (8, 2, 'ZentraleDV_M', 8); -- -------------------------------------------------------- -- -- Tabellenstruktur für Tabelle `tbl_filiale` -- CREATE TABLE `tbl_filiale` ( `FilialeID` int(11) NOT NULL, `FilialeBez` text NOT NULL, `FilialLeiterMbID_FK` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Daten für Tabelle `tbl_filiale` -- INSERT INTO `tbl_filiale` (`FilialeID`, `FilialeBez`, `FilialLeiterMbID_FK`) VALUES (1, 'Hamburg', 1), (2, 'München', 2); -- -------------------------------------------------------- -- -- Tabellenstruktur für Tabelle `tbl_mitarbeiter` -- CREATE TABLE `tbl_mitarbeiter` ( `MitarbeiterID` int(11) NOT NULL, `Nachname` text NOT NULL, `PersonalNr` text NOT NULL, `AbteilungID_FK` int(11) NOT NULL, `Gehalt` decimal(10,0) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Daten für Tabelle `tbl_mitarbeiter` -- INSERT INTO `tbl_mitarbeiter` (`MitarbeiterID`, `Nachname`, `PersonalNr`, `AbteilungID_FK`, `Gehalt`) VALUES (1, 'Meyer', '01V0001', 1, '5000'), (2, 'Müller', '02P0002', 6, '5500'), (3, 'Schulz', '01V0003', 1, '4500'), (4, 'Müller', '02V0004', 5, '4500'), (5, 'Wagner', '01VT0005', 3, '4500'), (6, 'Weber', '01IT0006', 4, '4500'), (7, 'Schulz', '02VT0007', 7, '4500'), (8, 'Reinhard', '02IT0008', 8, '4500'), (9, 'Siebert', '01P0009', 2, '4500'), (10, 'Schrader', '02P0010', 6, '4500'); -- -- Indizes der exportierten Tabellen -- -- -- Indizes für die Tabelle `tbl_abteilung` -- ALTER TABLE `tbl_abteilung` ADD PRIMARY KEY (`AbteilungID`); -- -- Indizes für die Tabelle `tbl_filiale` -- ALTER TABLE `tbl_filiale` ADD PRIMARY KEY (`FilialeID`); -- -- Indizes für die Tabelle `tbl_mitarbeiter` -- ALTER TABLE `tbl_mitarbeiter` ADD PRIMARY KEY (`MitarbeiterID`); -- -- AUTO_INCREMENT für exportierte Tabellen -- -- -- AUTO_INCREMENT für Tabelle `tbl_abteilung` -- ALTER TABLE `tbl_abteilung` MODIFY `AbteilungID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=9; -- -- AUTO_INCREMENT für Tabelle `tbl_filiale` -- ALTER TABLE `tbl_filiale` MODIFY `FilialeID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; -- -- AUTO_INCREMENT für Tabelle `tbl_mitarbeiter` -- ALTER TABLE `tbl_mitarbeiter` MODIFY `MitarbeiterID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11; COMMIT; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
Code:
-- Funktioniert bei aktiviertem ONLY_FULL_GROUP_BY, hat aber auch keine "überschüssige" Spalten: SELECT tbl_filiale.FilialeBez, t_fl.Nachname AS Filialleiter, t_fl.PersonalNr AS FilLeiterPNr , tbl_abteilung.AbteilungBez, t_abt.Nachname AS AbtLeiter, t_abt.PersonalNr AS AbtLeiterPNr , Sum(t_mb.Gehalt) AS SummevonGehalt FROM (((tbl_filiale INNER JOIN tbl_abteilung ON tbl_filiale.FilialeID = tbl_abteilung.FilialeID_FK) INNER JOIN tbl_mitarbeiter AS t_fl ON tbl_filiale.FilialLeiterMbID_FK = t_fl.MitarbeiterID) INNER JOIN tbl_mitarbeiter AS t_abt ON tbl_abteilung.AbteilungLeiterMbID = t_abt.MitarbeiterID) INNER JOIN tbl_mitarbeiter AS t_mb ON tbl_abteilung.AbteilungID = t_mb.AbteilungID_FK GROUP BY tbl_filiale.FilialeBez, Filialleiter, FilLeiterPNr, tbl_abteilung.AbteilungBez , AbtLeiter, AbtLeiterPNr ORDER BY tbl_filiale.FilialeID, tbl_abteilung.AbteilungID; -- Funktioniert nur bei deaktiviertem ONLY_FULL_GROUP_BY: SELECT tbl_filiale.FilialeBez, tbl_filiale.FilialeID, t_fl.Nachname AS Filialleiter , t_fl.PersonalNr AS FilLeiterPNr, tbl_abteilung.AbteilungBez, tbl_abteilung.AbteilungID , t_abt.Nachname AS AbtLeiter, t_abt.PersonalNr AS AbtLeiterPNr, Sum(t_mb.Gehalt) AS SummevonGehalt FROM (((tbl_filiale INNER JOIN tbl_abteilung ON tbl_filiale.FilialeID = tbl_abteilung.FilialeID_FK) INNER JOIN tbl_mitarbeiter AS t_fl ON tbl_filiale.FilialLeiterMbID_FK = t_fl.MitarbeiterID) INNER JOIN tbl_mitarbeiter AS t_abt ON tbl_abteilung.AbteilungLeiterMbID = t_abt.MitarbeiterID) INNER JOIN tbl_mitarbeiter AS t_mb ON tbl_abteilung.AbteilungID = t_mb.AbteilungID_FK GROUP BY tbl_filiale.FilialeID, Filialleiter, FilLeiterPNr, tbl_abteilung.AbteilungID , AbtLeiter, AbtLeiterPNr ORDER BY tbl_filiale.FilialeID, tbl_abteilung.AbteilungID; -- Funktioniert ebenfalls nur bei deaktiviertem ONLY_FULL_GROUP_BY: SELECT tbl_filiale.FilialeBez, t_fl.Nachname AS Filialleiter, t_fl.PersonalNr AS FilLeiterPNr , tbl_abteilung.AbteilungBez, t_abt.Nachname AS AbtLeiter, t_abt.PersonalNr AS AbtLeiterPNr , Sum(t_mb.Gehalt) AS SummevonGehalt FROM (((tbl_filiale INNER JOIN tbl_abteilung ON tbl_filiale.FilialeID = tbl_abteilung.FilialeID_FK) INNER JOIN tbl_mitarbeiter AS t_fl ON tbl_filiale.FilialLeiterMbID_FK = t_fl.MitarbeiterID) INNER JOIN tbl_mitarbeiter AS t_abt ON tbl_abteilung.AbteilungLeiterMbID = t_abt.MitarbeiterID) INNER JOIN tbl_mitarbeiter AS t_mb ON tbl_abteilung.AbteilungID = t_mb.AbteilungID_FK GROUP BY tbl_filiale.FilialeBez, tbl_abteilung.AbteilungBez ORDER BY tbl_filiale.FilialeID, tbl_abteilung.AbteilungID;
Kommentar