Announcement

Collapse
No announcement yet.

Bei leerem Abfrageergebnis Standardwerte setzen

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

  • Bei leerem Abfrageergebnis Standardwerte setzen

    Guten Abend,

    kann man bei einer Abfrage, deren Ergebnis ein leeres Egebnis ist, Standardwerte setzen?

    PHP Code:
    $SQL "SELECT bel.raumID, md5( concat( bel.buch, bel.platzID, bel.bel_status ) ) AS md5hash, 
                if( md5( concat( bel.buch, bel.platzID, bel.bel_status ) ) = '
    $_REQUEST[md5]', 'ja', 'nein' ) AS gueltig,
                pc. * , Date_Format( temp.arbeitbeginn, '%d.%m.%Y %H:%m:%s' ) AS tag, if( temp.raumID = '
    $_REQUEST[raumID]' AND temp.pcID != '$_REQUEST[pcID]', 'ja', 'nein' ) AS inBearbeitung
                    FROM `ac_alle_belegung` AS bel
                    LEFT JOIN ac_alle_temp AS temp ON temp.raumID = bel.raumID
                    LEFT JOIN ac_alle_pc AS pc ON pc.pcID = temp.pcID
                    WHERE bel.raumID = '
    $_REQUEST[raumID]'"
    ist wahrscheinlich mal wieder zu abstrakt.....

    Ich frage mich ob ich ein leeres Ergebnis trotzdem mit Werten füllen kann.

    wenn die bel.raumID = '$_REQUEST[raumID]'"; nicht vorhanden ist, wird ein leeres Ergebnis zurückgegeben.

    Sollte es so sein, müßte z.B bel.raumID die $_REQUEST[raumID'], md5hash die $_REQUEST[md5] und gueltig = ja erhalten

    aber vor allem sollte die PC Prüfung ( pc. * , Date_Format( temp.arbeitbeginn, '%d.%m.%Y %H:%m:%s' ) AS tag, if( temp.raumID = '$_REQUEST[raumID]' AND temp.pcID != '$_REQUEST[pcID]', 'ja', 'nein' ) AS inBearbeitung)

    in jedem Fall durchgeführt werden

  • #2
    Warum löst du das nicht in der Anwendung die die Abfrage benutzt? Ich sehe keinen Grund das ins SQL reinzufummeln.

    Comment


    • #3
      Originally posted by Ralf Jansen View Post
      Warum löst du das nicht in der Anwendung die die Abfrage benutzt? Ich sehe keinen Grund das ins SQL reinzufummeln.
      Ich finde es schon ansprechend, per SQL eine definierte Menge inkl. Grenzbereich zu erhalten. Vielleicht ist das Ansichtssache oder auch Wissenschaft, wahrscheinlich ist ein pragmatischer Kompromiss gefragt.

      Da gibt es sicher viele unterschiedliche Szenarien. Eins davon wäre, ich erwarte in der Anwendung genau 1 Ergebnis.
      Wenn ich das per Datenquelle, also SQL sicherstellen kann, spare ich mir idR eine Menge IF THEN ELSE gehampel im Anwednungscode. Das sieht dann leider oft so aus, dass die Kernfunktion ein 2 Zeiler ist und Grenzwertprüfungen dann doch 80% des Codes verschlingen. Also viel Tiparbeit und wenig übersichtlich.

      Bei einer erwarteten Ergebnismenge von 1 Datensatz kann man stumpf eine Aggregatfunktion anwenden, ohne Performanceprobleme befürchten zu müssen (pro Spalte, max oder min, macht kein Unterschied ).
      Das erzeugt erstmal eine Ergebnismenge 1, allerdings ohne Werte.

      Diesen "Null Case" kann man ideal auf einem PK Ergebnisfeld prüfen -sozusagen sicherheitshalber- und an den entscheidenden Stellen (Verarbeitung im Client) die richtigen Werte spendieren.

      Pro Feld sähe das in mySQL etwas so aus glaub ich (hier mit IfNull, ich komme von Oracle also NVL, denkbar sind auch Case oder Decode Äquivalente :
      Code:
      SELECT IFNULL(max(mcq.CoreTablePKField),<myDefinedValue>) as ResultID from myComplexQuery mcq where mcq.CoreTablePKField=myUniqueParam
      für eine 2. Spalte dann so:
      Code:
      SELECT IFNULL(max(mcq.CoreTablePKField),<myDefinedNullIDValue>) as ResultID,
                            IFNULL(max(mcq.CoreQueryResultField),<myDefinedNullCaseValue>) as ResultCase
         from myComplexQuery mcq where mcq.CoreTablePKField=myUniqueParam
      Zugegeben, die Unübersichtlichkeit hat sich nun Richtung SQL verschoben, was schwerer wiegt, muss von Fall zu Fall oder wie auch immer geregelt werden.
      Als Muster für solche Fälle ist es aber eigentlich leicht verständlich und man kann dem Anwendungsentwickler vorgeben, das da immer Ergebnisse kommen.

      Wenn ich das oben symbolisierte SQL Statement nun noch in einen View packe, gewinne ich eine Menge Kontrolle über das Anwendungsverhalten, ohne die Anwendung ändern / deployen zu müssen.
      Gruß, defo

      Comment


      • #4
        Diese IF statements hab ich ja schon eingesetzt.

        ABER.....

        PHP Code:
        SELECT IFNULL(max(mcq.CoreTablePKField),<myDefinedValue>) as ResultID from myComplexQuery mcq where mcq.CoreTablePKField=myUniqueParam 
        dein Beispiel liefert mir nur einen Datensatz,

        was oder wie bekomme ich denn mehrere datensätze angezeigt

        In meinem Beispiel:

        es erfolgt eine Ausgabe in einer Tabelle.
        mit dem klick in eine Zeile wird eine Routine ausgelöst, die den Vorhandenen Datensatz auf Gültigkeit prüfen soll.

        Es werden bestimmte Parameter geliefert wenn der Daten unverändert ist ( gueltig = ja z.B.)
        Wurde der Datensatz verändert erhalte ich ( gueltig = nein)
        Besteht der Datensatz nicht mehr brauche ich keinen leeren Datensatz sondern bestimmte (z.B oben genannte Parameter).

        Mit deinem Beispiel funktioniert dies bei einem gefundenen/nichtgefundenen Datensatz,
        es besteht jedoch die Möglichkeit bis zu 6 Treffer/ nichtTreffer zu haben. dann bekomme ich ja nur den größten gezeigt. Ich möchte aber alle angezeigt haben

        es kann naturlich sein, dass ich mit meinen Überlegungen auf dem Holzweg bin.

        Die Lösung in PHP hab ich , ich möchte meinen Code aber verkleinern und suche deshalb nach so einer SQL Lösung

        Comment


        • #5
          Originally posted by A.DA View Post
          Guten Abend,

          kann man bei einer Abfrage, deren Ergebnis ein leeres Egebnis ist, Standardwerte setzen?
          COALESCE ?

          Andreas

          Comment


          • #6
            Originally posted by A.DA View Post
            Mit deinem Beispiel funktioniert dies bei einem gefundenen/nichtgefundenen Datensatz,
            es besteht jedoch die Möglichkeit bis zu 6 Treffer/ nichtTreffer zu haben. dann bekomme ich ja nur den größten gezeigt. Ich möchte aber alle angezeigt haben
            Auf die Schnelle:
            Mein Beispiel funktioniert tatsächlich nur für einen Datensatz wg des Max. Das Max ist aber nur Mittel zum Zweck, um eben immer genau 1 DS zu erhalten.
            Wenn Du in einer beliebig großen Menge arbeitest, gibt es 2 Möglichkeiten:
            1) Menge > 0 und einige benötigte Werte bestimmter Spalten sind Null
            dort kannst Du einfach mit IFNULL ohne Max arbeiten und IFNULL einen definierten Wert mitgeben
            2) Menge insgesamt leer
            In diesem Fall kannst Du ein Aggregat über alle Spalten bilden (z.B. per Max) und darin IFNULL anwenden

            Die 2) ist allerdings nicht unbedingt empfehlenswert was Performance angeht. Die Operation kann ganz schön kosten.
            Evtl. bietet sich hier der Einsatz von Union an. Du fügst per Union immer einen virtuellen Datensatz dazu, der muss speziell gekennzeichnet sein, damit kein Blödsinn im "Normalfall" passiert. Dieses Kennzeichen kannst Du auswerten (IfNull geht dann wahrscheinlich nicht mehr, bzw. würdest Du den virtuellen Datensatz direkt so erzeugen, dass er die Werte enthält, die Du sonst bei IFNULL auswirfst)
            Gruß, defo

            Comment


            • #7
              Hallo,
              Originally posted by defo View Post
              Evtl. bietet sich hier der Einsatz von Union an. Du fügst per Union immer einen virtuellen Datensatz dazu, der muss speziell gekennzeichnet sein, damit kein Blödsinn im "Normalfall" passiert.
              Mann kann auch diesem "virtuellen" Datensatz eine entsprechende Bedingung verpassen, so dass er nur angezeigt wird wenn die ursprüngliche Menge leer ist.
              In etwa wie in der Pseudoabfrage:
              [highlight=sql]
              select a, b, c
              from abfrage1
              where bedingung
              union
              select 1, 2, 3
              where not exists (
              select 'X'
              from abfrage1
              where bedingung
              )
              [/highlight]
              Damit erhält man im Falle der "bedingung" alle Datensätze die dies erfüllen UND KEINEN weiteren. Im Falle der nicht erfüllten "bedingung" ist der eine DS mit den Standardwerten das Ergebniss.

              Gruß Falk
              Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

              Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

              Comment


              • #8
                Ja, das ist auch möglich. Kostet aber mglw. auch wieder.
                Gruß, defo

                Comment


                • #9
                  Ok, dann brauche ich ja nur meine Abfrage anpassen!!!

                  Danke für die Hilfe... werde es gleich mal ausprobieren.... denke ich werde nochmal Hilfe benötigen

                  Comment


                  • #10
                    Code:
                    SELECT buch, belegt_seit,bel_status
                    FROM ac_alle_belegung
                    WHERE raumID = 600
                    UNION
                    SELECT buch, belegt_seit,bel_status
                    WHERE NOT EXISTS (
                      SELECT 'X'
                     FROM ac_alle_belegung
                    WHERE raumID = 600
                    )
                    es erscheint
                    PHP Code:
                    .....er version for the right syntax to use near 'WHERE NOT EXISTS ( SELECT 'X' FROM ac_alle_belegung WHERE raumID = 600 ) L' at line 6 

                    Comment


                    • #11
                      Code:
                      SELECT buch, belegt_seit, bel_status
                      FROM ac_alle_belegung
                      WHERE raumID =600
                      UNION
                      SELECT 1 , 2, 3
                      FROM ac_alle_belegung
                      WHERE NOT
                      EXISTS (
                                  SELECT 'XX'
                                  FROM ac_alle_belegung
                                  WHERE raumID =600
                      )
                      wenn die raumID 600 nicht besteht gibt er mir 1 2 3 aus

                      was bezweckt denn der code zwischen den ()

                      Comment


                      • #12
                        Originally posted by A.DA View Post
                        wenn die raumID 600 nicht besteht gibt er mir 1 2 3 aus

                        was bezweckt denn der code zwischen den ()
                        Du kannst den Code ja mal entfernen und schauen was passiert.

                        Es bezweckt genau was Falk geschrieben hat. Du hast allerdings einen From Teil eingebaut der in seinem Vorschlag nicht dabei ist.
                        Ist Dir klar was eine virtuelle Tabelle / Zeile ist?

                        Nimm doch einfach nur den Teil hinter Union und lass ihn allein laufen:
                        Code:
                        SELECT 1 , 2, 3
                        FROM ac_alle_belegung
                        WHERE NOT
                        EXISTS (
                                    SELECT 'XX'
                                    FROM ac_alle_belegung
                                    WHERE raumID =600)
                        Vor allem entferne das From acalle_belegung oder schau dir den Unterschied mit/ohne und geänderter Where Bedingung an.
                        Gruß, defo

                        Comment


                        • #13
                          wenn ich das (from .... ) hinter 1,2,3 wegnehme bekomme ich ne Fehlermeldung

                          #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE NOT EXISTS ( SELECT 'XX' FROM ac_alle_belegung ' at line 3

                          Comment


                          • #14
                            Originally posted by A.DA View Post
                            wenn ich das (from .... ) hinter 1,2,3 wegnehme bekomme ich ne Fehlermeldung
                            Oh, das liegt wohl an der folgenden Where Clause.

                            Mir war nicht klar, dass mysql sich da so anstellt.

                            Es geht eigentlich darum:
                            Du brauchst für diese Teilabfrage keine Quelltabelle, erst recht nicht die von Dir verwendete, vermutlich große Tabelle. Du brauchst nur garantiert einen Datensatz. Das ist bei verschiedenen Datenbanken verschieden umgesetzt.
                            Bei mySQL einfach From Clause weglassen .. (Im Detail klemmt's aber wohl- wie Dein Beispiel zeigt)
                            Bei oracle 'from dual' verwenden- dual ist eine Hilfstabelle mit genau einem Datensatz
                            kompatibel zu Oracle gibt's das auch bei MySQL.

                            das ergibt mindestens 2 Möglichkeiten:
                            Select 1,2,3 kapseln, Alias vergeben
                            Code:
                            Select * from (SELECT 1 , 2, 3) x
                            WHERE NOT
                            EXISTS (
                                        SELECT 'XX'
                                        FROM ac_alle_belegung
                                        WHERE raumID =600)
                            oder dual verwenden
                            Code:
                            SELECT 1 , 2, 3 from dual 
                            WHERE NOT
                            EXISTS (
                                        SELECT 'XX'
                                        FROM ac_alle_belegung
                                        WHERE raumID =600)
                            Der Dual Ansatz ist wie gesagt eine Kompatibilitäts-Funktion zu Oracle. Bei ganz alten mySQL Versionen gab's da Problem.
                            Vielleicht geht das noch eleganter, bin kein mySQL Spezi.
                            Gruß, defo

                            Comment


                            • #15
                              Code:
                              SELECT *
                              FROM (
                              
                              SELECT 1 AS erste, 2 AS zweite, 3 AS dritte
                              )x
                              WHERE NOT
                              EXISTS (
                              
                              SELECT *
                              FROM ac_alle_belegung
                              WHERE raumID =600
                              )
                              Soweit hab ichs jetzt... der Vorschlag funktioniert.

                              jetzt baue ich sie mal um.

                              in der belegung sind die vergebenen raumID abgelegt.
                              in der ac_alle_temp die pcID, die eine raumID zurzeit bearbeiten.

                              es kann also durchaus passieren, dass eine raumID in der belegung noch nicht vorhanden ist, aber in der temp schon ( da datensatz evtl. angelegt oder gelöscht wurde)

                              ich versuch mich mal....

                              kann ich den zu den 1 2 3 auch echte Abfragewerte beifügen? wenn das szenario wie oben beschrieben eintritt

                              Comment

                              Working...
                              X