Announcement

Collapse
No announcement yet.

Felder aus mehreren Tabellen abfragen

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

  • #16
    Originally posted by Urwi View Post
    Ja, die "Createstatements" waren von Anfang an da. Ich weiß ja wie ich mich zu benehmen habe ;-)

    "Full Outer Join", was immer das auch ist, Google wird es mir verraten.
    Okay, dann habe ich es jetzt schriftlich, danke!
    Full Outer Joins sind kurz erklärt die Kombination aus left (outer) join und right (outer) join. Also quasi die "lockerste" Form von Join, die man sich denken kann. Danach kommt glaub ich nichts außer Cross Join / Permutation, jeder mit jedem sozusagen. Natürlich ganz jugendfrei.
    Oracle kann das tatsächlich noch nicht so lange (ab 10?), glaub ich, obwohl es eine relativ lange spezifizierte Join Form (ANSI SQL xy) ist. Aber sie haben immer (traditionell) ihre eigene "Join " Syntax per where clause und (+) gehabt und scheinbar war das so eine Art Stiefkind mit dem full outer join. Vielleicht erzählich aber auch gerade Quatsch.
    Gruß, defo

    Comment


    • #17
      Vielleicht erzählich aber auch gerade Quatsch.
      Zumindest klingt es gut ;-)

      Danke

      Comment


      • #18
        Originally posted by Urwi View Post
        Zumindest klingt es gut ;-)
        Also mit Quatsch meinte ich nur die "Historie" zu oralce full outer join.
        Die Erklärung ist kurz, aber kein Quatsch, höchstens k(w)arg.
        Gruß, defo

        Comment


        • #19
          War auch nur ironisch gemeint.

          Comment


          • #20
            Hallo defo,

            ich habe deine Lösung jetzt mit mehreren Varianten probiert und bin leider auf einen Fehler gestoßen. Leider komme ich da jetzt nicht wirklich weiter.
            Code:
             
            create table tab_vn 
            (  Id              NUMBER(10)           not null,
               Vorname         VARCHAR2(60)         not null,
               BearbeitetAm    DATE
            );
            
            
            create table tab_nn 
            (  Id              NUMBER(10)           not null,
               Nachname        VARCHAR2(60)         not null,
               BearbeitetAm    DATE
            );
            
            
            create table tab_GD 
            (  Id            NUMBER(10)           not null,
               GebDat        DATE                 not null,
               BearbeitetAm  DATE
            );
            
            INSERT INTO tab_vn VALUES(  1, 'vorname_01', '09.01.2013' );
            INSERT INTO tab_vn VALUES(  2, 'vorname_02', '09.11.2013' );
            INSERT INTO tab_vn VALUES(  3, 'vorname_03', '09.01.2014' );
            
            INSERT INTO tab_nn VALUES(  1, 'nachname_01', '09.01.2013' );
            INSERT INTO tab_nn VALUES(  2, 'nachname_02', '19.11.2013' );
            
            INSERT INTO tab_gd VALUES(  1, '15.10.1949', '09.01.2013' );
            INSERT INTO tab_gd VALUES(  2, '15.10.1948', '09.01.2014' );
            INSERT INTO tab_gd VALUES(  3, '01.03.1966', '09.01.2014' );
            
            
            	 select n.*, v.*, g.*,
                   nvl(n.bearbeitetam, nvl(v.bearbeitetam, g.bearbeitetam)) AnyOfGivenDate
              from            tab_vn v
              full outer join tab_nn n  on v.bearbeitetam = n.bearbeitetam
              full outer join tab_gd g  on n.bearbeitetam = g.bearbeitetam
             order by 10, 2, 4, 6
            
            Das Ergebnis der Abfrage ist:
            Code:
             
            VORNAME       NACHNAME        GEBDAT         ANYOFGIVENDATE                    
            ----------------------------  ----------------------------- 
            vorname_01    nachname_01     15.10.1949     09.01.2013
            vorname_02                                   09.11.2013
                          nachname_02                    19.11.2013
            vorname_03                                   09.01.2014
                                          15.10.1948     09.01.2014
                                          01.03.1966     09.01.2014
            
            Aber richtigerweise sollte das herauskommen:
            Code:
             
            VORNAME       NACHNAME        GEBDAT         ANYOFGIVENDATE                    
            ----------------------------  -----------------------------
            vorname_01    nachname_01     15.10.1949     09.01.2013
            vorname_02                                   09.11.2013
                          nachname_02                    19.11.2013
            vorname_03                    15.10.1948     09.01.2014
            vorname_03                    01.03.1966     09.01.2014
            
            Vielleicht könntest du mir da nochmals unter die Arme greifen, weil ich da keine Lösung finde.

            Danke
            Urwi

            Comment


            • #21
              Hast Du nur keine Lösung gefunden oder ist Dir auch die Ursache nicht klar?

              Wenn Du Dir anschaust, was womit gejoint wird, dürfte sich dieses Bild ergeben:
              Ein full outer join produziert per Definition aus 2 Mengen eine Vereinigungmenge, in Deinem fall anhand eines Feldes als Joinkriterium.
              Ein full outer join für 3 Mengen gibt es aber nicht, also wird in meinem Beispiel "gestückelt" und zwar unvollständig.

              In meinem Beispiel werden nicht alle Kombinationen der Tabellen gejoined.
              Nur v mit n und n mit g, n ist dadurch ein Bindeglied, das Gleichheit zwischen v und g nicht abdeckt, wenn sie in n fehlt.
              Du brauchst mehr etwas sternförmiges statt eine "Verkettung"

              Du musst also alles noch mal umrühren, gibt sicher verschiedene Wege, das zu lösen. Z.B. die full outer join nicht auf einer Ebene anzulegen, sondern Teilmengen zu bilden.
              Erst nur ein Full Outer Join n:v und das Ergebnis noch mal Full Outer zu g, also (n:v):g. Mein Beispiel wäre eher v:n:g.

              Cool wäre jetzt, wenn ich in Mathe Mengenlehre richtig aufgepasst hätte, dann könnte ich das nett hinschreiben.

              Aber versuch mal, wird schon klappen.
              Gruß, defo

              Comment


              • #22
                Hallo defo,

                ich habe keine Lösung gefunden!
                Zuerst war ich der Meinung, dass alles richtig läuft, bis ich auf dieses Beispiel gestoßen bin. Grundsätzlich ist mir schon das "full outer Join" suspekt. Genau darüber stolpere ich, weil es 3 Mengen sind.
                Ich habe auf schon das Ganze über eine virtuelle Tabelle mit den gesamten Daten probiert, aber auch da komme ich nicht auf einen grünen Zweig. Leider sind meine Kenntnisse in Oracle total veraltet und daher sehr unzureichend. Google hilft in solch spezifischen Fällen auch nicht weiter. Ich habe auch ein Beispiel in verschiedenen Varianten über ein Union zu lösen versucht, aber da kommt auch nicht das Richtige raus. Sprich 3 Select in denen ich die Tabellen untereinander austausche. Ich glaube, mit jedem Versuch "verschlimmbessere" ich die Sache.
                Wenn ich über Oracle die Lösung nicht finde, programmiere ich das aus.

                vg

                Comment


                • #23
                  Originally posted by Urwi View Post
                  Leider sind meine Kenntnisse in Oracle total veraltet und daher sehr unzureichend. Google hilft in solch spezifischen Fällen auch nicht weiter. Ich habe auch ein Beispiel in verschiedenen Varianten über ein Union zu lösen versucht, aber da kommt auch nicht das Richtige raus. Sprich 3 Select in denen ich die Tabellen untereinander austausche.

                  Wenn ich über Oracle die Lösung nicht finde, programmiere ich das aus.
                  Ach komm, Du musst das Beispiel nur umbauen. Nichts neues nur klammern / anders schachteln. Behaupte ich jetzt mal.
                  Und das mit dem "alter" hatten wir doch schon.

                  Und Ausprogrammieren klingt ja schon fast wie eine Drohung...

                  Ich schau vielleicht heute Abend rein, hab keine Muße grad.
                  Gruß, defo

                  Comment


                  • #24
                    Eine Lösung habe ich, aber ob das in jeder Konstellation funktioniert muss ich erst austesten:

                    Code:
                    
                    select nachname, vorname, gebdat, nvl(n.bearbeitetam, nvl(v.bearbeitetam, g.bearbeitetam)) AnyOfGivenDate
                       from            tab_vn v
                       LEFT outer join tab_nn n  on n.bearbeitetam = v.bearbeitetam
                       LEFT outer join tab_gd g  on g.bearbeitetam = v.bearbeitetam
                    	
                    UNION
                    
                     select nachname, vorname, gebdat, nvl(n.bearbeitetam, nvl(v.bearbeitetam, g.bearbeitetam)) AnyOfGivenDate
                       from            tab_nn n
                       LEFT outer join tab_vn v  on v.bearbeitetam = n.bearbeitetam
                       LEFT outer join tab_gd g  on g.bearbeitetam = n.bearbeitetam	
                    	
                    UNION
                    
                     select nachname, vorname, gebdat, nvl(n.bearbeitetam, nvl(v.bearbeitetam, g.bearbeitetam)) AnyOfGivenDate
                       from            tab_gd g
                       LEFT outer join tab_vn v  on v.bearbeitetam = g.bearbeitetam
                       LEFT outer join tab_nn n  on n.bearbeitetam = g.bearbeitetam	
                    	
                    ORDER BY 4	
                    
                     

                    Comment


                    • #25
                      Originally posted by Urwi View Post
                      Eine Lösung habe ich, aber ob das in jeder Konstellation funktioniert muss ich erst austesten:
                      Ok, Union ist sicher eine Möglichkeit, das nimmt man aber nicht ohne Not, vor allem dann, wenn die Datenquelle tatsächlich unterschiedlich ist oder vielleicht aus völlig disjunkten Teilmengen besteht. (Kommt natprlich auf die Datenmengen an, tut nur weh, wenn sie groß sind)
                      Dann machst Du da etwas-der Wechsel left /right (outer) join bzw. das Tauschen der Datenquellen Reihenfolge, das aufs Gleiche hinausläuft, was eeigentlich in Systemen, die kein full outer kennen als Workaround verwendet wird.
                      Siehe hier z.B. https://stackoverflow.com/questions/...-join-in-mysql
                      Damit bist Du vielleicht gar nicht so weit weg vom Verständnis eines Full Outer Joins, wie Du behauptest.

                      Außerdem produziert der Union hier in diesem Fall unnötig viele (Zwischenergebnis)Daten, die nachher wieder rausfliegen (weil: Union enthält sozusagen ein Distinct)

                      Also lieber per Join, dann hat der Optimizer die Chance, das beste draus zu machen.

                      Ich hatte eher an sowas gedacht (ungetestet)
                      Code:
                      select x.*, nvl(x.AnyOfGivenDate, g.bearbeitetam) AnyOfGivenDateFinal from (
                        select n.*, v.*, 
                               nvl(n.bearbeitetam, v.bearbeitetam) AnyOfGivenDate
                          from            tab_vn v
                          full outer join tab_nn n  on v.bearbeitetam = n.bearbeitetam
                                                                                                )x 
                        full outer join tab_gd g  on x.AnyOfGivenDate = g.bearbeitetam
                       order by 10, 2, 4, 6  -- order by noch auf die neue Spalte anpassen
                      Vielleicht ist das auch Quatsch mit dem Oberen NVL, oder das ganze Statement ist Quatsch, hab da grad kein Kopf für.
                      Gruß, defo

                      Comment


                      • #26
                        "full outer Join" suspekt.
                        Vielleicht hilft eine visuelle Erklärung der JOIN-Typen weiter: https://www.codeproject.com/Articles...n-of-SQL-Joins
                        MfG
                        Cheat-Sheets for Developers / Programming Quotes

                        Comment


                        • #27
                          Originally posted by Markus Lahr View Post
                          Vielleicht hilft eine visuelle Erklärung der JOIN-Typen weiter: https://www.codeproject.com/Articles...n-of-SQL-Joins
                          Danke, sehr interessant!

                          Comment


                          • #28
                            Hallo defo,

                            hier ist die "Not", möglichst schnell zu einer richtigen Lösung zu kommen. Die Anzahl der Datensätze bewegt sich insgesamt vielleicht auf 2000-3000 Stück, wobei diese noch extrem eingeschränkt werden, weil sie einer bestimmten Person zugeordnet werden. Die Verwendung der Abfrage ist beschränkt, weil die Daten in eine richtige Datenstruktur kommen soll.

                            Danke
                            Urwi

                            Comment


                            • #29
                              Originally posted by Urwi View Post
                              hier ist die "Not", möglichst schnell zu einer richtigen Lösung zu kommen. Die Anzahl der Datensätze
                              Meine Anmerkungen sind grundsätzlicher Natur- wir sind ja in einem Forum. Wenn es andere Prioritäten gibt, als Speed oder was auch immer, kann man das natürlich nach Bedarf priorisieren.

                              Hier ist eine bereinigte Version meines 2.Vorschlags:
                              [highlight=sql]
                              select x.vorname, x.nachname, g.gebdat, x.AnyOfGivenDate
                              -- nvl(x.AnyOfGivenDate, g.bearbeitetam) AnyOfGivenDateFinal
                              from (select n.ID as IDn, n.NACHNAME as NACHNAME,
                              n.BEARBEITETAM as BEARBEITETAMn, v.ID as IDv,
                              v.VORNAME as VORNAME, v.BEARBEITETAM as BEARBEITETAMv,
                              nvl(n.bearbeitetam, v.bearbeitetam) AnyOfGivenDate
                              from tab_vn v
                              full outer join tab_nn n
                              on v.bearbeitetam = n.bearbeitetam) x
                              full outer join tab_gd g
                              on x.AnyOfGivenDate = g.bearbeitetam
                              order by 4, 1, 2, 3
                              [/highlight]

                              Wenn Du das mit anderen Lösungen auf Ergebnisebene vergleichen willst, wäre ein einfacher Ansatz 2 Statements mit Minus zu verbinden (wie bei union).
                              Gruß, defo

                              Comment


                              • #30
                                Hallo defo,

                                bin heute nicht im Büro, werde aber morgen einmal deine Lösung ausprobieren.

                                Danke
                                Urwi

                                Comment

                                Working...
                                X