Lukas.: mysql: Query gesucht

Moin,

ich habe 3 Tabellen und suche eine Query hierfür. Vorab, ich habe diese Tabellen vor etlichen Jahren angelegt und bin grad' selber sehr unglücklich über die Redundanzen und sonstigen strukturellen "Besonderheiten". Es ist nur grad der falsche Zeitpunkt, sich hierum zu kümmern, da ich in Folge eines strukturellen Umbaus zu viele Nachfolgearbeiten in den Scripten haben würde. Aber versprochen, ich werde mich darum später kümmern.

Zum Problem und ggf. zum Nachvollziehen des Problems:


CREATE TABLE IF NOT EXISTS `lt_products` (
  `LTID` int(6) NOT NULL,
  `LID` int(6) NOT NULL DEFAULT '1',
  `PID` int(6) NOT NULL DEFAULT '1',
  `Menge` float(10,2) NOT NULL DEFAULT '0.00',
  `Preis` decimal(10,2) DEFAULT '0.01',
  `Nachlass` decimal(4,2) DEFAULT '0.00',
  `MID` int(6) NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT;

CREATE TABLE IF NOT EXISTS `tb_products` (
  `TBID` int(6) NOT NULL,
  `MID` int(5) NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT;

CREATE TABLE IF NOT EXISTS `t_products` (
  `TID` int(6) NOT NULL,
  `TBID` int(5) NOT NULL DEFAULT '0',
  `TAnzahl` decimal(6,2) DEFAULT '0.00',
  `TVK` decimal(10,2) DEFAULT NULL,
  `MwstSatz` decimal(4,2) NOT NULL
) ENGINE=MyISAM DEFAULT;

-- -----------------------------------------------------------------------------------

INSERT INTO `lt_products` (`LTID`, `LID`, `PID`, `Menge`, `Preis`, `Nachlass`, `MID`) VALUES
(122, 35, 2646, 2.00, '44.00', '0.00', 4619),
(123, 35, 2647, 2.00, '55.00', '10.00', 4619);

INSERT INTO `tb_products` (`TBID`, `MID`) VALUES
(2268, 4619),
(2269, 4619);

INSERT INTO `t_products` (`TID`, `TBID`, `TAnzahl`, `TVK`, `MwstSatz`) VALUES
(2646, 2268, '2.00', '44.00', '21.00'),
(2647, 2269, '2.00', '55.00', '20.00');

-- -----------------------------------------------------------------------------------

Nun möchte ich die Summen aller lt-Produkte abzüglich Nachlass, aber mit dem MwSt-Satz aus der t_products-Tabelle.

Leider geht mir über meine Queries immer der Nachlass flöten.

Das liegt an meiner Subquery, in der der Nachlass bereits nicht enthalten ist.

SELECT t.TAnzahl AS Menge, 
 t.TVK AS VK, 
 lt.Nachlass AS Nachlass
 FROM t_products t 
 JOIN tb_products tb ON t.TBID = tb.TBID 
 LEFT JOIN lt_products lt ON tb.MID = lt.MID 
 WHERE t.MwstSatz = '20.00' 
 AND tb.MID = 4619 
 GROUP BY t.TID

Wenn man die Gruppierung wegläßt, wirds noch klarer. Dann habe ich eine Ergebnismange mit 2 Zeilen, eine mit Nachlass und eine ohne.

Wie muss die Query lauten, damit der Nachlass beinhaltet ist?

L.

  1. Tach!

    Nun möchte ich die Summen aller lt-Produkte abzüglich Nachlass, aber mit dem MwSt-Satz aus der t_products-Tabelle.

    Was muss ich mir unter Summen vorstellen? Ich sehe keine Summierung in deiner Query noch eine so benannte Spalte.

    Leider geht mir über meine Queries immer der Nachlass flöten. Das liegt an meiner Subquery, in der der Nachlass bereits nicht enthalten ist.

    Eine Subquery/Subselect sehe ich auch nicht.

    Wie muss die Query lauten, damit der Nachlass beinhaltet ist?

    Zum Nachvollziehen, sag mir doch bitte, welche Daten aus welchen Tabellen du benötigst, und das bitte jeweils einzeln pro Tabelle zunächst ohne die anderen Tabellen zu beachten. Als nächstes möchte ich wissen, wie diese Daten miteinander verknüpft werden müssen, um zum Ergebnis zu kommen. Dazu ein Beispiel anhand konkreter Zahlenwerte wäre auch nicht verkehrt.

    dedlfix.

    1. Hi dedlfix,

      Was muss ich mir unter Summen vorstellen? Ich sehe keine Summierung in deiner Query noch eine so benannte Spalte.

      Eine Subquery/Subselect sehe ich auch nicht.

      Meine Query ist bereits die "isolierte" Subquery. Weil der Fehler in der Ergebnismenge dieser Subquery enthalten ist, habe ich den Rest der Query erst gar nicht gepostet. Weil wir uns eh auf diesen Teil der Gesamtquery hätten konzentrieren müssen.

      Zum Nachvollziehen, sag mir doch bitte, welche Daten aus welchen Tabellen du benötigst, und das bitte jeweils einzeln pro Tabelle zunächst ohne die anderen Tabellen zu beachten. Als nächstes möchte ich wissen, wie diese Daten miteinander verknüpft werden müssen, um zum Ergebnis zu kommen. Dazu ein Beispiel anhand konkreter Zahlenwerte wäre auch nicht verkehrt.

      Fast hätte ich das im Ausgangspost schon gemacht. Ich dachte, mein Posting würde hierdurch zu lang, also dann jetzt hier:

      t_products: Hier brauch ich nur den MWSt.-Satz

      lt_products: Hier brauch ich Menge, Preis, Nachlass

      Das wars eigentlich schon:

      Herauskommen muß quasi folgender Rechenvorgang für "WHERE t.MwstSatz = '20.00' AND tb.MID = 4619":

      2 x 55 x (1-10/100) = 99
      

      lt_products: LTID ist primary Key, PID ist der Schlüssel zu TID der t_products-Tabelle

      t_products: TID ist primary Key, TBID ist Schlüssel zu tb_products Tabelle

      tb_products: TBID ist primary Key

      Ich hoffe, das sind vollständige Informationen, ansonsten bitte melden.

      L.

      1. Wenn das so ist, dann frage ich mich, warum Du den "langen" Weg über TB nimmst, der deine Eindeutigkeit zerstört, statt direkt und eindeutig LT und T über PID=TID zu joinen.

        Dass deine Subquery von MYSQL eigentlich als defekt abgewiesen werden müsste, bleibt davon unberührt. Und wenn Du nach einem Primary Key gruppierst, kommt pro Gruppe immer nur ein Satz raus, das kann also nicht sinnvoll sein.

        Rolf

        1. Wenn das so ist, dann frage ich mich, warum Du den "langen" Weg über TB nimmst, der deine Eindeutigkeit zerstört, statt direkt und eindeutig LT und T über PID=TID zu joinen.

          Die Eindeutigkeit dürfte doch hierdurch nicht zerstört werden? Außerdem brauche ich die TB-Tabelle auch, da ich hier die MID heraus ziehe. Ich bitte mal darum, die MID aus der LT-Tabelle zu ignorieren, weil ich diese Spalte gerne herauslöschen würde.

          Dass deine Subquery von MYSQL eigentlich als defekt abgewiesen werden müsste, bleibt davon unberührt. Und wenn Du nach einem Primary Key gruppierst, kommt pro Gruppe immer nur ein Satz raus, das kann also nicht sinnvoll sein.

          Und nu?

          L.

          1. Tach!

            Wenn das so ist, dann frage ich mich, warum Du den "langen" Weg über TB nimmst, der deine Eindeutigkeit zerstört, statt direkt und eindeutig LT und T über PID=TID zu joinen.

            Die Eindeutigkeit dürfte doch hierdurch nicht zerstört werden?

            Na doch. Ausgehend von t joinst du tb über TBID, was noch eine 1:1-Beziehung ist. Dann kommt lt hinzu über MID, und das ergibt ein kartesisches Produkt, weil über die 4619 deine jeweils beiden Test-Datensätze 2x2=4 miteinander verknüpft werden. Das willst du doch bestimmt nicht haben und versuchst das über die Gruppierung wieder herauszukürzen.

            Dein Nachlass geht verloren, weil in der Gruppe keine eindeutigen Werte zu finden sind. Bei Mwst=20 hast du einen Datensatz mit Nachlass 0 und einen mit 10 im kartesischen Produkt. Die Gruppierung ist kaputt und funktioniert nur bei pro Gruppe eindeutigen Daten. Andere Systeme als MySQL lassen sie deshalb in der Form nicht zu.

            Außerdem brauche ich die TB-Tabelle auch, da ich hier die MID heraus ziehe.

            Wenn du t direkt mit lt verbindest, hast du doch die MID bereits in lt stehen. Wozu also bindest du die tb ein?

            Ich bitte mal darum, die MID aus der LT-Tabelle zu ignorieren, weil ich diese Spalte gerne herauslöschen würde.

            Dann verstehe ich noch weniger, warum du über die tb-Tabelle gehst.

            SELECT
              t.TAnzahl AS Menge, 
              t.TVK AS VK, 
              lt.Nachlass AS Nachlass,
            
              TAnzahl * TVK * (1 - lt.Nachlass / 100) as gesucht
            FROM t_products t
            LEFT JOIN lt_products lt ON t.TID = lt.PID
            

            Ist das nicht, was du suchst?

            dedlfix.

            1. Hi dedlfix,

              Na doch. Ausgehend von t joinst du tb über TBID, was noch eine 1:1-Beziehung ist. Dann kommt lt hinzu über MID, und das ergibt ein kartesisches Produkt, weil über die 4619 deine jeweils beiden Test-Datensätze 2x2=4 miteinander verknüpft werden. Das willst du doch bestimmt nicht haben und versuchst das über die Gruppierung wieder herauszukürzen.

              So ist es.

              Ich bitte mal darum, die MID aus der LT-Tabelle zu ignorieren, weil ich diese Spalte gerne herauslöschen würde.

              Dann verstehe ich noch weniger, warum du über die tb-Tabelle gehst.

              Inwiefern? Ich brauche die Selektion nach der MID.

              SELECT
                t.TAnzahl AS Menge, 
                t.TVK AS VK, 
                lt.Nachlass AS Nachlass,
              
                TAnzahl * TVK * (1 - lt.Nachlass / 100) as gesucht
              FROM t_products t
              LEFT JOIN lt_products lt ON t.TID = lt.PID
              

              Ist das nicht, was du suchst?

              Im Prinzip schon, jedenfalls wenn ich die MID aus der lt-Tabelle ziehe. Das wollte ich aber eigentlich vermeiden…

              L.

              1. Wenn die MID dein Einstieg in die Suche ist, und Du sie aus der LT entfernen willst, solltest Du auch nicht darüber JOINen.

                Warum nimmst Du nicht diesen JOIN:

                SELECT t.TAnzahl AS Menge
                     , t.TVK AS VK
                     , lt.Nachlass AS Nachlass
                FROM tb_products TB
                     JOIN t_products T ON t.TBID = tb.TBID
                     LEFT JOIN lt_products ON lt.PID = t.TID
                WHERE tb.MID = 4619
                  AND t.MwstSatz = '20.00' 
                

                Wobei du einen JOIN auch durch einen Subselect ersetzen kannst:

                SELECT t.TAnzahl AS Menge
                     , t.TVK AS VK
                     , (SELECT Nachlass FROM lt_products lt WHERE lt.PID = t.TID) AS Nachlass
                FROM tb_products tb
                     JOIN t_products t ON t.TBID = tb.TBID
                WHERE tb.MID = 4619
                  AND t.MwstSatz = '20.00' 
                

                Rolf

                1. Wenn die MID dein Einstieg in die Suche ist, und Du sie aus der LT entfernen willst, solltest Du auch nicht darüber JOINen.

                  Ich dachte, es wäre kein Unterschied, ob ich darüber joine oder es direkt hinter das FROM notiere?

                  Warum nimmst Du nicht diesen JOIN:

                  SELECT t.TAnzahl AS Menge
                       , t.TVK AS VK
                       , lt.Nachlass AS Nachlass
                  FROM tb_products TB
                       JOIN t_products T ON t.TBID = tb.TBID
                       LEFT JOIN lt_products ON lt.PID = t.TID
                  WHERE tb.MID = 4619
                    AND t.MwstSatz = '20.00' 
                  

                  #1054 - Unknown column 'lt.Nachlass' in 'field list' (warum auch immer)

                  Wobei du einen JOIN auch durch einen Subselect ersetzen kannst:

                  SELECT t.TAnzahl AS Menge
                       , t.TVK AS VK
                       , (SELECT Nachlass FROM lt_products lt WHERE lt.PID = t.TID) AS Nachlass
                  FROM tb_products tb
                       JOIN t_products t ON t.TBID = tb.TBID
                  WHERE tb.MID = 4619
                    AND t.MwstSatz = '20.00' 
                  

                  Der ist schön. Ist das eine korrelierte Subquery?

                  L.

                  1. Ich dachte, es wäre kein Unterschied, ob ich darüber joine oder es direkt hinter das FROM notiere?

                    Ob die Reihenfolge, in der Tabellen mit JOIN verbunden werden, relevant ist, darüber müsste ich jetzt erstmal sinnieren (von LEFT/RIGHT JOIN mal abgesehen, da ist es logisch dass die Reihenfolge wichtig ist). Ich würde vermuten, dass es bei einem INNER oder FULL JOIN tatsächlich egal ist. Es ging mir aber um was anderes. Zum einen solltest Du keine neuen Queries auf LT.MID aufbauen, wenn das Feld obsolet ist. Und zum anderen: Wenn Du die LT-Tabelle über die MID anbindest, bekommst Du mehr als einen LT-Treffer pro Zeile in T. Wenn Du die Anbindung über LT.PID=T.TID machst, ist die Beziehung eindeutig und du hast genau einen LT-Treffer pro Zeile in T, und das ist das, was Du willst. Glaube ich jedenfalls :)

                    Der Error 1054 kommt, weil ich den LT Alias hinter lt_products vergessen habe.

                    Und ja, sowas ist eine korrelierte Subquery. Subquery weil es - naja, eine untergeordnete Query ist und korreliert kommt von Co-Relation, heißt also soviel wie "im Zusammenhang stehend". Der Zusammenhang wird hergestellt durch den Zugriff auf den Tabellen-Alias T, der zur äußeren Query gehört.

                    Rolf

                    1. Hi Rolf,

                      Der Error 1054 kommt, weil ich den LT Alias hinter lt_products vergessen habe.

                      Hätte ich selber drauf kommen dürfen. Ich habe nun die korrelierte Version genommen.

                      SELECT t.TAnzahl * t.TVK * (1-(SELECT Nachlass FROM lt_products lt WHERE lt.PID = t.TID)/100)
                      FROM tb_products tb
                      JOIN t_products t ON t.TBID = tb.TBID
                      WHERE tb.MID = 4619
                      AND t.MwstSatz = '20.00'
                      

                      Und ja, sowas ist eine korrelierte Subquery. Subquery weil es - naja, eine untergeordnete Query ist und korreliert kommt von Co-Relation, heißt also soviel wie "im Zusammenhang stehend". Der Zusammenhang wird hergestellt durch den Zugriff auf den Tabellen-Alias T, der zur äußeren Query gehört.

                      Darf ich das Problem noch etwas ausbauen? 🌝

                      Es gibt Fälle, in denen ich die Menge nicht aus der t-Tabelle nehmen möchte, sondern aus einer LM-Tabelle. Hierzu gibt es also 2 weitere Tabellen, die nötig sind, zu kennen: "lm und l"

                      lm_products: LID (primary), LTID (Schlüssel zu lt_products),Menge,Index (Schlüssel zu l_products),LID (kann als Schlüssel zu l_products und/oder lt_products verendet werden)

                      l_products: LID (primary), Index, MID (dieselbe wie in tb_products)

                      Kann ich obige Query so erweitern, dass ich die Mengen nicht aus der t_products-Tabelle, sondern anstatt dessen aus der lm_products-Tabelle nehme?

                      L.

                      1. SELECT t.TAnzahl * t.TVK * (1-(SELECT Nachlass FROM lt_products lt WHERE lt.PID = t.TID)/100)
                        FROM tb_products tb
                        JOIN t_products t ON t.TBID = tb.TBID
                        WHERE tb.MID = 4619
                        AND t.MwstSatz = '20.00'
                        

                        Kann ich obige Query so erweitern, dass ich die Mengen nicht aus der t_products-Tabelle, sondern anstatt dessen aus der lm_products-Tabelle nehme?

                        'Habs versucht, zu joinen, geht aber nicht, weil mein Alias lt aus der korrelierten Subquery in der "Außenquery" unbekannt ist... ich überleg mal weiter…

                        L.

                      2. Tach!

                        Es gibt Fälle, in denen ich die Menge nicht aus der t-Tabelle nehmen möchte, sondern aus einer LM-Tabelle.

                        Ich sag mal IF()-Funktion und in den einen Zweig den Feldzugriff, in den anderen die Subquery für die Ermittlung aus der anderen Tabelle.

                        Kann ich obige Query so erweitern, dass ich die Mengen nicht aus der t_products-Tabelle, sondern anstatt dessen aus der lm_products-Tabelle nehme?

                        Erstmal die Subquery als eigenständige Query erstellen und testen, ohne Korrelation dafür mit festen Test-Werten, dann einbauen und korrelieren.

                        dedlfix.

                        1. Hi dedlfix,

                          Ich sag mal IF()-Funktion und in den einen Zweig den Feldzugriff, in den anderen die Subquery für die Ermittlung aus der anderen Tabelle.

                          Wäre eine Möglichkeit, ich kann aber auch eine komplett 2. neue Query machen, da ich ich per Parameter der Funktion mitteile, welche Query zu nutzen sein soll.

                          Erstmal die Subquery als eigenständige Query erstellen und testen, ohne Korrelation dafür mit festen Test-Werten, dann einbauen und korrelieren.

                          Das versuche ich gerade, aber bisher mit mittelmäßigem Erfolg.

                          Ich dachte mir, den Anfang:

                          SELECT t.TAnzahl * t.TVK * (1-(SELECT Nachlass FROM lt_products lt WHERE lt.PID = t.TID)/100)

                          umzuschreiben in

                          SELECT lm.Menge* t.TVK * (1-(SELECT Nachlass FROM lt_products lt WHERE lt.PID = t.TID)/100)

                          und lm_products sinnvoll zu joinen, aber bisher wie gesagt, geht es so schonmal nicnht bei mir.

                          L.

                          1. So, ich habe die Lösung gefunden.

                            Allerdings ist mir der JOIN nicht innerhalb der Lösung2 von Rolf (korrelierte Subquery) gelungen. In Lösung 1 von Rolf war es hingegen relativ einfach.

                            Danke an Rolf und dedlfix für Eure Hilfe.

                            L.

              2. Tach!

                [kartesisches Produkt] Das willst du doch bestimmt nicht haben und versuchst das über die Gruppierung wieder herauszukürzen.

                So ist es.

                Am besten ist, solche Datenmengen gar nicht erst entstehen zu lassen, die man dann sowieso wieder zusammenkürzt. Dann vermeidet man auch die daraus entstehenden Probleme. Lieber fünf verschachtelte Subquerys und davon drei nebeneinander, bei denen aber eindeutige Datenmengen entstehen als ein Join mit einem ungewollten kartesischen Produkt.</übertreibung>

                Ich bitte mal darum, die MID aus der LT-Tabelle zu ignorieren, weil ich diese Spalte gerne herauslöschen würde.

                Dann verstehe ich noch weniger, warum du über die tb-Tabelle gehst.

                Inwiefern? Ich brauche die Selektion nach der MID.

                🤔 Du verwirrst mich. Brauchst du nun die MID oder nicht? Das Problem was ich habe ist, dass ich den Sinn der Datenstruktur nicht erfassen kann, zum Beispiel warum die so verknüpft sind wie sie sind, und deshalb meine sinngemäßen Antwortmöglichkeiten eingeschränkt sind. Die Abkürzungen in den Bezeichnern sind tragen ihren Teil dazu bei. Mit sprechenden Bezeichnern könnte ich mir ja vielleicht noch was zusammenreimen.

                Ist das nicht, was du suchst?

                Im Prinzip schon, jedenfalls wenn ich die MID aus der lt-Tabelle ziehe. Das wollte ich aber eigentlich vermeiden…

                Braucht es noch eine andere Lösung? Wenn ja, warum?

                dedlfix.

                1. Hi dedlfix,

                  Am besten ist, solche Datenmengen gar nicht erst entstehen zu lassen, die man dann sowieso wieder zusammenkürzt. Dann vermeidet man auch die daraus entstehenden Probleme. Lieber fünf verschachtelte Subquerys und davon drei nebeneinander, bei denen aber eindeutige Datenmengen entstehen als ein Join mit einem ungewollten kartesischen Produkt.</übertreibung>

                  Merke ich mir.

                  🤔 Du verwirrst mich. Brauchst du nun die MID oder nicht?

                  Ja, ich brauche sie. Aber nicht aus der lt-Tabelle, sondern aus der tb-Tabelle. Grund ist, dass ich die Spalte aus der lt-Tabelle gerne löschen würde.

                  Das Problem was ich habe ist, dass ich den Sinn der Datenstruktur nicht erfassen kann, zum Beispiel warum die so verknüpft sind wie sie sind, und deshalb meine sinngemäßen Antwortmöglichkeiten eingeschränkt sind. Die Abkürzungen in den Bezeichnern sind tragen ihren Teil dazu bei. Mit sprechenden Bezeichnern könnte ich mir ja vielleicht noch was zusammenreimen.

                  Kann ich nachvollziehen. Leider fällt es mir bei genau diesem Problem fast selber schwer, die Verknüpfungen noch genau nachzuvollziehen, weil ich das heute eher etwas anders gelöst hätte.

                  Braucht es noch eine andere Lösung? Wenn ja, warum?

                  Weil ich die Spalte MID aus der lt-Tabelle gerne löschen würde. Dafür hat RolfB nun 2 Lösungen erwähnt, von denen ich gerne 1 nehmen würde. (Die mit der korrelierten Subquery gefällt mir. Sowas hattest Du übrigens schonmal vor graumer Zeit bei einem sehr ähnlichen Problem vorgeschlagen).

                  Ich brauche aber tatsächlich, aufbauend auf diesem Problem tatsächlich noch eine weitere Lösung, die ich gerne hier beschreiben möchte.

                  L.

    2. Wenn das die Subquery ist, dann ist sie syntaktisch falsch, weil bei Vorliegen eines GROUP BY eine bei SELECT angegebene Spalte entweder unter GROUP BY aufgelistet sein oder aggregiert (SUM, AVG, ...) werden muss.

      Ansonsten stimme ich Dedlfix zu - deine Frage ist sehr verworren.

      Und ich stimme Dir zu - den Datenmodell ist sehr verworren. Du hast einmal eine m:n Beziehung zwischen LT und T, dargestellt mit der TB Tabelle, und andererseits scheinst Du auch eine 1:1 Beziehung zu haben, dargestellt über LT.PID und T.TID. Ist es Zufall, dass die preislich zueinander passenden Zeilen in LT und T hier die gleichen ID-Werte haben?

      Rolf

      1. Hallo Rolf,

        Wenn das die Subquery ist, dann ist sie syntaktisch falsch, weil bei Vorliegen eines GROUP BY eine bei SELECT angegebene Spalte entweder unter GROUP BY aufgelistet sein oder aggregiert (SUM, AVG, ...) werden muss.

        Sorry, im Original ist tatsächlich im Select noch eine Spalte mehr drin:

        SELECT t.TAnzahl AS Menge, 
         t.TVK AS VK, 
         lt.Nachlass AS Nachlass, 
         t.TID 
         FROM t_products t 
         JOIN tb_products tb ON t.TBID = tb.TBID 
         LEFT JOIN lt_products lt ON tb.MID = lt.MID 
         WHERE t.MwstSatz = '20.00' 
         AND tb.MID = 4619 
         GROUP BY t.TID
        

        Und ich stimme Dir zu - den Datenmodell ist sehr verworren.

        Es ist fürchterlich! Zwar als Datenmodell relativ einfach zu normalisieren, aber der Sxcriptteil wird etwas länger dauern.

        Ist es Zufall, dass die preislich zueinander passenden Zeilen in LT und T hier die gleichen ID-Werte haben?

        Nein, das ist ihr Schlüssel zueinander.

        L.

        1. So, hab mal wieder was gelernt. Ich habe SQL in den 80er Jahren beigebracht bekommen, und das MySQL Handbuch sagt:

          For the query to be legal in SQL92, a nonaggregated column must be omitted from the select list or named in the GROUP BY clause.

          SQL99 and later permits such nonaggregates per optional feature T301 if they are functionally dependent on GROUP BY columns: If such a relationship exists between tid and TAnzahl, TVK and Nachlass, the query is legal. This would be the case, for example, were custid a primary key of customers.

          Ich habe die Spaltennamen aus dem Handbuch durch die Spaltennamen aus deinem Beispiel ersetzt.

          Demnach ist deine QUERY so nicht völlig legal. Die funktionale Abhängigkeit zwischen tid und TAnzahl und TVK besteht, weil TID der Primary Key der T Tabelle ist. Die funktionale Abhängigkeit zwischen TID und Nachlass besteht nicht, weil MID kein eindeutiger Key in die LT Tabelle ist.

          Nun greift offenbar eine andere Logik, die im MYSQL 5.6 Handbuch beschrieben ist: Wenn eine nonaggregate Column nicht im GROUP BY aufgeführt ist, weist er das Statement nicht ab, sondern wählt einfach einen beliebigen Wert aus der Gruppe. Bei Dir offenbar die 0. Hättest Du für PID=2646 einen Wert ungleich 0 für den Nachlass drin, dann würdest Du vermutlich den sehen.

          Rolf

          1. Nun greift offenbar eine andere Logik, die im MYSQL 5.6 Handbuch beschrieben ist: Wenn eine nonaggregate Column nicht im GROUP BY aufgeführt ist, weist er das Statement nicht ab, sondern wählt einfach einen beliebigen Wert aus der Gruppe. Bei Dir offenbar die 0. Hättest Du für PID=2646 einen Wert ungleich 0 für den Nachlass drin, dann würdest Du vermutlich den sehen.

            Hi Rolf,

            dann wärs mir aber eigentlich lieber, mysql würde die Query abweisen. Weil, wenn ichs vergessen hätte, zu testen, würde n un ein Fehler in der Query schlummern, der mir irgendwann auf die Füße fällt. 😕

            L.

            1. Tach!

              dann wärs mir aber eigentlich lieber, mysql würde die Query abweisen.

              Kann man glaube ich so konfigurieren, dass derartige Abfragen Fehler werfen.

              Weil, wenn ichs vergessen hätte, zu testen, würde n un ein Fehler in der Query schlummern, der mir irgendwann auf die Füße fällt. 😕

              Wichtiger war es, eine Möglichkeit zu haben, bei nicht normalisierten Daten Gruppierungen vornehmen zu können. Performance war ein wichtiges Kriterium bei der Entwicklung. Redundante Daten sind schneller abgefragt als normalisierte Daten verknüpft sind.

              Und wenn du nicht prüfst, ob deine Abfragen die Ergebnisse bringen, die du dir vorstellst, ist ja nicht die Technik schuld. Es gibt auch noch genügend Fälle, bei denen du mit standardkonformen Abfragen nicht die Ergebnisse bekommst, die zu deinem Anwendungsfall passen, weil du irgendeinen fachlichen Aspekt nicht beachtet hast. Testen gehört genauso dazu wie die Erkenntnisse, Sonderfälle übersehen zu haben.

              dedlfix.

              1. Und wenn du nicht prüfst, ob deine Abfragen die Ergebnisse bringen, die du dir vorstellst, ist ja nicht die Technik schuld.

                ...

                Testen gehört genauso dazu wie die Erkenntnisse, Sonderfälle übersehen zu haben.

                Zum einen gings mir nicht um Schuld oder nciht, zum anderen, je komplexer ein System wird, desto mehr gibt es zum testen. Es gibt teilweise so viele Eventualitäten, wie Du sie selber gar nciht mehr bedenken kannst. Geschweige denn, auf welch aberwitzige Ideen User oft kommen (gar nicht böse gemeint), auf die mußt Du erstmal selber kommen... aber das weißt Du sicher selber auch. Mir geht es jedenfalls so, dass mir das Entwickeln deutlich mehr Spaß macht als das testen, kinsofern wäre mir hier eine Fehlermeldung lieber gewesen.

                L.

                1. Was ich heute Mittag dazu gefunden habe, ist:

                  GROUP BY Handling in MYSQL

                  Achte drauf, ob deine MYSQL Version dazu passt.

                  Die Steuerung erfolgt demnach über die Variable sql_mode, und wenn meine Experimente mich nicht getrogen haben, darf man die nicht einfach setzen, sondern muss mit Stringverkettung arbeiten um die übrigen Schalter nicht zu überschreiben.

                  SET SESSION sql_mode = CONCAT(@@SESSION.sql_mode, ",ONLY_FULL_GROUP_BY")

                  Ich weiß nicht, ob ich die Nummer mit dem SQL_MODE richtig verstanden habe. Das ist eine Liste von kommaseparierten Werten, man kann den sql_mode für die SESSION oder GLOBAL setzen (letzteres sollte man eher lassen bzw. in der MYSQL Config machen, nicht per SQL Statement), und wenn man erstmal was gesetzt hat, kriegt man es nur pre String-Parsing wieder raus (oder man merkt sich den alten Wert und stellt ihn wieder her). Klingt für mich erstmal nach gruseligem API Design.

                  Vielleicht weiß @dedlfix besser, wie man damit umgeht...

                  Rolf

                  1. Tach!

                    Vielleicht weiß @dedlfix besser, wie man damit umgeht...

                    Nein, ich lass das so wie es ist und beachte Gruppierungen einfach so. Lukas hatte ja nun sein Erlebnis damit und wird sich wohl auch ohne konkretes Schimpfen von MySQL beim nächsten Vorkommen erinnern.

                    dedlfix.