Ankündigung

Einklappen
Keine Ankündigung bisher.

MAX() in einer foreach Schleife

Einklappen

Neue Werbung 2019

Einklappen
Dieses Thema ist geschlossen.
X
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • #61
    Zitat von Meister1900 Beitrag anzeigen

    Die MySQL Entwickler begründen das unter https://dev.mysql.com/doc/refman/5.7...-handling.html so:
    1. 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.
    2. 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.
    3. 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?
    4. 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.
    5. 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.
    Es folgen nun ein paar Abfragen, die zeigen, daß die Detektion nicht immer funktioniert und daß für solche Abfragen die Deaktivierung von ONLY_FULL_GROUP_BY sinnvoll und hilfreich ist:

    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 */;
    ABFRAGEN
    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


    • #62
      marie123 oder wie auch immer...
      Unglaublich wie viel Energie du in ein Problem investierst, das für die Meisten gar nicht existiert.
      Dass du zudem Muttersprachlern die Fähigkeit absprichst Formulierungen richtig zu verwenden setz, meiner Meinung nach, dem Ganzen die Krone auf und zeigt wie lächerlich du dich machst.

      Kommentar


      • #63
        protestix einfach ignorieren, würde ich vorschlagen. Ich bin eh raus: tl;dr. Diese Diskussion ist schlicht flüssiger als Wasser. Also überflüssig.
        PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

        Kommentar


        • #64
          Um mal etwas FÜR MySQL zu sagen (oh Gott, die Hölle friert ein...): es kann offenbar "loose index scan" oder auch als "skip index scan" bekannte Dinge, die PG (derzeit) nicht kann - zumindest nicht direkt. Siehe https://wiki.postgresql.org/wiki/Loose_indexscan . Das ist cool. Richtig cool! Ich hab grad ein Ticket, wo es um sowas geht... der Workaround funktioniert, und ein Patch (für 13?) ist in Sicht, ... stay tuned for more!
          PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

          Kommentar


          • #65
            Zitat von akretschmer Beitrag anzeigen
            einfach ignorieren, würde ich vorschlagen.
            Nein! Ich weiß nicht, wie man so borniert sein kann, falsche Ergebnisse zu ignorieren und mit irgendwelchen menschlichen Case ..When .. Kascaden zu übertünchen. Wie man on top die Sinnhaftigkeit des extra von den Entwicklern ergänzten Reparaturschalters in Abrede stellen kann und auch noch versucht zu vermitteln, dass es gerade für Anfänger eine prima Sache ist, mit dieser Scheiße zu lernen.

            Wo ist der Benefit, was ist das Lernplus an diesem System? Bitte aufführen, was es gerade für Anfänger so lernenswert und vorteilhaft macht!
            Ich werde mich jeder einzelnen Antwort und jedem genannten Feature widmen!

            Kommentar


            • #66
              Boah, Du hast so Recht! Ich hab es einfach in den Skat gedrückt
              PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

              Kommentar


              • #67
                Zitat von Perry Staltic Beitrag anzeigen

                Nein! Ich weiß nicht, wie man so borniert sein kann, falsche Ergebnisse zu ignorieren ...
                Sei doch bitte so freundlich und höflich, richtig zu lesen und auch zu verstehen. In welchem Teil/Satz meiner Ausführungen ignoriere ich falsche Ergebnisse?

                Kommentar


                • #68
                  Öhm... Wie war die Frage nochmal? Ach ja... ist ja bereits seit #35 gelöst für den TE...

                  [MOD: geschlossen]
                  Competence-Center -> Enjoy the Informatrix
                  PHProcks!Einsteiger freundliche TutorialsPreComposed Packages

                  Kommentar

                  Lädt...
                  X