Announcement

Collapse
No announcement yet.

EXISTS-Problem?

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

  • EXISTS-Problem?

    Guten Abend!

    Ich möchte aus einer Tabelle TB_M in einer DB2-DB alle Datensätze selektieren, die bei einer gleichen S_NR und bei einer gleichen M_NR sowohl die M_NR = 6 als auch die M_NR = 7 haben. Mit anderen Worten: Es gibt einen Datensatz mit einer S_NR und einer M_NR, der hat in dem Feld M_NR den Wert 6. Und es gibt einen Datensatz, der die die gleiche S_NR und die gleiche M_NR hat wie der eben genannte Datensatz, aber in dem Feld M_NR den Wert 7 hat. Nur diese beiden Datenstäze möchte ich ermitteln.

    Leider erhalte ich in diesem SELECT nicht nur die gesuchten Datensatzpaare, sondern auch einen Datensatz, der nur einen der beiden mögliichen Zahleneinträge (6 bzw. 7) in M_NR hat.

    Code:
    SELECT  TB_M.S_NR, TB_M.M_NR
    FROM TB_M a 
    WHERE a.AKT = 1
    AND EXISTS (SELECT 'X' FROM TB_M b WHERE b.S_NR = a.S_NR and b.M_NR = 6 )
    AND EXISTS (SELECT 'X' FROMTB_M c WHERE c.S_NR = a.S_NR and c.M_NR = 7 )
    AND M_NR IN (6, 7)
    Nach meinen Aufzeichnungen entspricht das IN einem logischen oder. Ich benötige aber ein logisches UND.

    Könnte mir bitte jemand weiterhelfen, meine SQL.Kenntnisse sind zu klein.
    Vielen Dank!!

  • #2
    Dazu könnte man sich mehrere Wege vorstellen. Frage wäre noch, ob Du in der Ausgabe beide Sätze brauchst oder einer der beiden reicht.
    1) In Deinem Beispiel eine Exists Clause durch direkte Gleichheit ersetzen
    also statt

    [highlight=sql]AND EXISTS (SELECT 'X' FROM TB_M b WHERE b.S_NR = a.S_NR and b.M_NR = 6 )
    AND EXISTS (SELECT 'X' FROMTB_M c WHERE c.S_NR = a.S_NR and c.M_NR = 7 )
    [/highlight]
    eher
    [highlight=sql]
    AND a.M_NR = 6 )
    AND EXISTS (SELECT 'X' FROMTB_M c WHERE c.S_NR = a.S_NR and c.M_NR = 7 )
    [/highlight]

    2) bei hoher Selektivität (und überschaubarer Datenmenge) von a.Akt=1 und M_NR IN (6, 7)
    ginge auch ein simples Join von s_nr zwischen Menge 1 where m_r=6 und Menge 2 where m_nr = 7
    Das hätte mglw. noch den Vorteil, dass Du im Ergebnissatz nach Bedarf den 6er oder 7er Satz darstellen bzw auswerten und darstellen kannst.

    3) Falls es in DB2 sowas wie Analytic Functions gibt, kannst Du eine einzige Menge mit
    m_r in (6,7) bilden, den m_nr Vorgänger dazuholen und prüfen, ob der Vorgänger von m_nr = m_nr-1 ist. Dann hättest Du alle 7er Sätze in einem Durchlauf/Scan, was auch immer, je nach Indizierung. Schau einfach was der Ausführungsplan sagt.

    Alles ungeprüft, nur Ideen.
    Gruß, defo

    Comment


    • #3
      Hallo Neuer,

      auch wenn deine Abfrage, wie defo es gezeigt hat, noch optimiert werden kann,
      wundert es mich, dass nicht das korrekte Ergebnis herauskommt.
      Einen Fehler im Statement kann ich auch nicht entdecken.
      Wenn ich mich recht entsinne hatte ich Mal mit EXISTS Probleme, wenn das Feld den Wert NULL hat.

      Alternativ geht's auch so:
      [highlight=sql]
      SELECT TB_M.S_NR, TB_M.M_NR
      FROM TB_M
      INNER JOIN (SELECT S_NR
      FROM TB_M
      WHERE AKT = 1
      GROUP BY S_NR
      HAVING
      SUM(CASE WHEN M_NR = 6 THEN 1 ELSE 0 END) > 0
      AND SUM(CASE WHEN M_NR = 7 THEN 1 ELSE 0 END) > 0
      )Nr6und7
      ON TB_M.S_NR = Nr6und7.S_NR
      AND AKT = 1
      [/highlight]
      Und Falk Prüfer sprach: Formatierung von SQL in Beiträgen

      Comment


      • #4
        Hallo knoxyz!


        Vielen Dank, daß Du Dir Zeit für mein Problem genommen hast.

        Heute habe ich keine Zeit, Deine Lösung nachzuvollziehen. Werde es aber morgen oder Montag machen.

        Ich habe mir zwischenzeitlich diese, eine ganz andere Lösung ausgedacht. Diese ist aber deswegen komplizierter, weil ich aus fachlichen Gründen vor meinem eigentlichen Problem einen INNER JOIN machen muß. So kommt es, daß ich zwei INNER JOINS habe. Zudem habe ich noch etwas mehr Felder, dich verschweigen habe, um mit meiner Frage noch mehr Verwirrung zu stifften.


        Code:
        SELECT DISTINCT                                  
               TB_V.B_NR,             
               TB_V.V_NR        
                                                         
        FROM TB_V                    
                                                         
        INNER JOIN TB_M AS A ON (              
               TB_V.V_NR =      
               TB_M.V_NR    
                                                         
        AND                                              
               TB_V.B_NR =            
               TB_M.B_NR)         
                                                         
        INNER JOIN TB_M AS B ON                
              (A.V_NR =               
               B.V_NR                 
                                                         
        AND                                              
              A.B_NR =                      
              B.B_NR)                       
                                                         
        WHERE (B.MM_AKTKZ = 1 AND B.M_MR = 7       
              AND A.AKT = 1 AND A.M_MR = 6    
              AND TB_V.GUEL = 1)
        Mein Statement scheint zu funktionieren. Ich bin mir aber nicht sicher, da ich zu selten SQL-Statements bilden muss.

        Nochmals vielen Dank für Deine Unterstützung!!!!

        Viele Grüße

        Neuer

        Comment

        Working...
        X