Announcement

Collapse
No announcement yet.

MySQL Abfrage liefert zwei Datensätze, aber nur einer soll angezeigt werden

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • MySQL Abfrage liefert zwei Datensätze, aber nur einer soll angezeigt werden

    Wir wollen ein Shop-System an unsere Bedürfnisse anpassen. Mit der MySQL Abfrage sollen alle Produkte einer bestimmten Artikelkategorie ermittelt werden. Der eingeloggte Kunde hat einen bestimmten Rabattsatz für jede Kategorie. Bei einigen Artikeln dieser Kategorie bekommt er jedoch einen besonderen Rabatt. In der verknüpften Tabelle ist also ein Eintrag mit product_id 0 und dem Standardrabatt und einer mit einer bestimmten product_id und dem speziellen Rabatt.
    Code:
    left join " . TABLE_CUSTOMERS_DISCOUNT  . " cd 
       on cd.customers_id ='" .(int) $customer_id. "' 
       and cd.categories_id = '" .(int) $current_category_id. "'                                  
       and IF(cd.product_id !='0',cd.product_id =  p.products_id),
    Das Problem ist, dass der Artikel einmal mit dem speziellen Rabatt, aber auch mit dem Standard-Rabatt angezeigt wird. Wie kann man den Datensatz mit dem Standard-Rabatt ausblenden wenn ein Eintrag mit der aktuellen product_id vorhanden ist?
    Danke - Günther
    Günther

  • #2
    Ihn rausfiltern.
    ... speziellen Rabatt!=null oder was auch immer der Standardwert ist.
    Zuletzt editiert von Christian Marquardt; 29.05.2017, 18:55.
    Christian

    Comment


    • #3
      In der Tabelle discount gibt es den Datensatz mit product_id 42 und den mit product_id 0. Beide haben die categorie_id 7.

      In der Tabelle products gibt es zu categorie_id 7 die Datensätze mit product_id 42 und 43.
      Der Datensatz mit product_id 43 wird mit dem discount-Datensatz zu product_id 0 verknüpft, wegen der Übereinstimmung der categorie_id => Standard-Rabatt.
      Der Datensatz mit product_id 42 passt aber zu beiden discount Datensätzen, weil einmal die product_id übereinstimmt => spezieller Rabatt
      und im anderen Fall stimmt die categorie_id überein => Standard-Rabatt.

      Während ein Datensatz untersucht wird müßte MySQL also wissen, dass es noch einen weiteren Datensatz gibt der diesen wieder ungültig macht.

      Wenn das mit MySQL nicht geht, muss man das Abfrageergebnis nachträglich durchlaufen ob eine product_id zweimal gefunden wird und dann den Datensatz mit der cd.product_id 0 rausschmeißen, glaube ich.
      Günther

      Comment


      • #4
        Dann sollte es doch mit einem case ..when gehen, wenn bestimmt werden kann welcher vorrangig ist (anhand der Reihenfolge im case when)
        Christian

        Comment


        • #5
          Originally posted by Christian Marquardt View Post
          Dann sollte es doch mit einem case ..when gehen, wenn bestimmt werden kann welcher vorrangig ist (anhand der Reihenfolge im case when)
          Ich glaube nicht, damit hätte man eine "horizontale" Unterscheidung und könnte Spalten tauschen oder sowas.

          Ich hab die Beschreibung noch nicht richtig verstanden.

          Wenn 2 gleiche Datensätze vorhanden sind, die über kein exaktes Unterscheidungsmerkmal besitzen bzw. kein exaktes Joinkriterium vorliegt, müssten sie sortiert und gewichtet werden anhand der verfügbaren Unterschiede. Das könnte man mit Ranking machen, Windows Funktions, die gibt es aber unter mySQL nicht. Müsste man dann irgendwas basteln. Das ergäbe dann wohl ein brauchbares Filterkriterium.
          Wird vielleicht nicht besonders flott sein, zumindest nicht bei großen Datenmengen.

          Der Join Abschnitt oben sieht so aus, als ob der Product Join offen bleibt, wenn keine Referenz eingetragen ist und damit quasi irgendeine Permutation stattfindet. Ohne Beispieldaten und ein vollständiges Selectstatement alles schwer zu sagen.
          Gruß, defo

          Comment


          • #6
            ist das nicht ein und das selbe? Nur, dass CASE bei vielen Möglichkeiten übersichtlicher ist...

            Code:
             
            CASE case_value
               WHEN when_value THEN when_statement_list
               ELSE else_statement_list
            END CASE
            Code:
            IF search_condition THEN if_statement_list
                ELSE else_statement_list
            END IF
            Günther

            Comment


            • #7
              Ich habe mir Mühe gegeben, nur den wesentlichen Teil der Abfrage zu posten. Aber wenn es hilft, bitte sehr:


              Code:
              $listing_sql = "select " . $select_column_list . " p.products_id, p.manufacturers_id, p.products_price, p.products_tax_class_id, 
              IF(true, p.products_price*(100-cd.Rabatt)/100, NULL) as specials_new_products_price, 
              IF(true, p.products_price*(100-cd.Rabatt)/100, p.products_price) as final_price 
              
              from " . TABLE_PRODUCTS_DESCRIPTION . " pd, " . TABLE_PRODUCTS . " p 
              
              left join " . TABLE_MANUFACTURERS . " m on p.manufacturers_id = m.manufacturers_id  
              left join  " . TABLE_SPECIALS . " s on p.products_id = s.products_id 
              left join " . TABLE_CUSTOMERS_DISCOUNT  . " cd 
                 on cd.customers_id ='" .(int) $customer_id. "' 
                 and IF(cd.product_id !='0',cd.categories_id = '" .(int) $current_category_id. "' 
                 and cd.product_id =  p.products_id, cd.categories_id = '" .(int) $current_category_id. "'),
                 " . TABLE_PRODUCTS_TO_CATEGORIES . " p2c 
                 
                 where p.products_status = '1' 
                 and p.products_id = p2c.products_id 
                 and pd.products_id = p2c.products_id 
                 and pd.language_id = '" . (int)$languages_id . "' 
                 and p2c.categories_id = '" . (int)$current_category_id . "'";
              Günther

              Comment


              • #8
                Originally posted by Günther Weber View Post
                Ich habe mir Mühe gegeben, nur den wesentlichen Teil der Abfrage zu posten. Aber wenn es hilft, bitte sehr:
                Helfen tut es kaum, aber besser als nichts bzw als die Zeilen am Anfang. Daten und Tabellendefinition dazu, dann könnte man einigermaßen Aussagen treffen.
                Falls Du Dich wirklich bemüht hast, keine unnötige Information zu liefern, so ist das nicht gelungen bzw. Du bist über das Ziel hinaus geschossen. Ich habe selbst schon häufiger gepostet, ein Problem vor der Veröffentlichung in einem Forum auf das Wesentliche zu reduzieren. Aber das bedeutet nicht bloß, ein paar Zeilen auszuschneiden.

                Reduktion auf das Wesentliche bedeutet, ein funktionierendes Beispiel des Problems zu liefern, minus der Felder, Tabellen und Abfrageteile, die das problematische Ergebnis nicht beeinflussen. Das bedeutet natürlich etwas Mühe, erhöht aber die Chance auf Verständnis und Hilfe. Im Ergebnis hätte man ein Szenario, was in diesem Fall bspw auf die Mehrsprachigkeit verzichtet, eine Zeile weniger in der Where Clause usw.

                Ich sage mal grundsätzlich:
                Der wesentliche Teil einer SQL Abfrage ist die gesamte Abfrage.

                Das gilt vor allem, wenn weder die Felddefinitin, noch die Constraints, noch die Daten der abgefragten Elemente bekannt sind.
                Denn normalerweise gehören Tabellendefinitionen und die Daten, ggf die Indizierung zusätzlich zum Definitionsrahmen, der die Ergebnismenge und ggF. Performance bestimmt. Je weniger Constraints definiert sind, desto wichtiger die Beispieldaten, usw usw.

                Ist das Statement so original oder ist es schon verändert?
                Gruß, defo

                Comment


                • #9
                  Ich selbst programmiere nicht an dieser MySQL Abfrage, ich kümmere mich darum dass die Datenbank immer aktuelle Daten aus der Warenwirtschaft bekommt.
                  Der Kollege der vor diesem Problem steht will mir aber morgen mehr Informationen zukommen lassen.
                  Günther

                  Comment


                  • #10
                    Ist ja in Ordnung, nimm es bitte nicht persönlich. Der Kollege kann ja auch hier mitmachen. Mund-zu-Mund-Beatmung macht man ja auch meist auf direktem Weg.
                    Will heißen, der Informationstransfer wird idR nicht besser, wenn er über mehrere Personen läuft.

                    Mir fehlt leider die Vorstellungskraft ausgerechnet dieses Statement in dem Kontext durch bloße Regelanwendung und Fallableitung zu verbessern. In einem modifizierten Shopsystem erst Recht, das ist sowieo ein heißes Eisen. Ob Ihr Euch auf die Art überhaupt einen Gefallen tut, wage ich zu bezweifeln.

                    Also wichtig wäre neben Datenmodel usw. die Frage, ist es bereits modifiziert und wenn ja wie sieht das Original aus?
                    Rein Interesse halber, was ist das für ein Shopsystem?
                    Gruß, defo

                    Comment


                    • #11
                      Der Kollege kann noch nicht mitreden, er hat noch keine Bestätigungsmail.
                      Das System ist "Powered by osCommerce". Genaueres wird der Kollege sagen können.

                      Die Tabelle mit den Rabatten ist aber nicht Original, die haben wir hinzugefrickelt.

                      Code:
                      CREATE TABLE `customers_discount` (
                          `customers_discount_id` INT(11) NOT NULL AUTO_INCREMENT,
                          `customers_id` INT(11) NOT NULL,
                          `categories_id` INT(11) NOT NULL,
                          `product_id` INT(11) NULL DEFAULT NULL,
                          `Rabatt` DOUBLE NULL DEFAULT NULL,
                          PRIMARY KEY (`customers_discount_id`)
                      )
                      COLLATE='latin1_swedish_ci'
                      ENGINE=InnoDB
                      AUTO_INCREMENT=150
                      ;

                      Günther

                      Comment


                      • #12
                        Meine Zahlenwerte, gestern 19:07 Uhr hatte ich "aus dem Kopf", sie passen nicht so ganz zu den Daten im Bild
                        Attached Files
                        Günther

                        Comment


                        • #13
                          Ich vermute mal, dass Ihr dass so gemacht habt, weil ihr die Originaltabellen nicht ändern wollt? Die vorliegenden Daten sagen zwar noch nichts über das gesamte Modell aber nun denn,

                          erster Vorschlag auf die Schnelle in Worten:
                          Die customers_discount Tabelle ein 2. Mal joinen, eingeschränkt auf reine Category Referenzen. Dieser Join wird ebenfalls left gemacht.
                          Der join zwischen Category und Product wird unconditional gemacht, "if" also raus.
                          Damit erhält man im Ergebnis 2 Rabatte, aber nicht untereinander in Form 2er Produkte, sondern nebeneinander.
                          Das ist dann die Stunde von Case (siehe oben), Case entscheidet nun, welcher Rabatt eingesetzt wird.

                          Statement zum 2. Einbinden:
                          (Select .. from customers_discount where product_id!=0) as x

                          Zu dem "gefrickelten original":
                          Ich hab mit Shopsystemen nichts am Hut, aber ich find es beruhigend, dass es nicht original ist.
                          Das If Construct läuft darauf hinaus, dass in dem einen Fall einfach ein Join weggelassen wird. Was macht eine DB Engine daraus? Sie nimmt alles was geht, mischt jeden Teil der einen Menge mit jedem der anderen Menge. Das will sicher niemand, aber so sind halt die Regeln und das Ergebnis ist unbrauchbar (wenn es überhaupt zustande kommt)

                          Probiert das mal aus.
                          Gruß, defo

                          Comment


                          • #14
                            Hi defo,
                            Es funktioniert :-)
                            Danke
                            Günther

                            Comment


                            • #15
                              Originally posted by Günther Weber View Post
                              Hi defo,
                              Es funktioniert :-)
                              Danke
                              Sehr schön!
                              Hab gerade bemerkt, dass mein Vorschlag für "2.Einbindung" falsch ist, müsste "=0" sein für die Discounts ohne Produktanbindung, nicht "!=0"

                              Aber habt Ihr wahrscheinlich selber auch bemerkt.

                              Schön wäre ja, wenn Ihr das Ergebnis noch hier präsentiert, dann haben andere auch was davon.
                              Zuletzt editiert von defo; 31.05.2017, 23:35.
                              Gruß, defo

                              Comment

                              Working...
                              X