Announcement

Collapse
No announcement yet.

Differenz zwischen Tabellen

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

  • Differenz zwischen Tabellen

    Hey Community,

    ich hoffe, dass ihr mir bei folgenden Problem helfen könnt.

    Ich habe zwei Tabellen die identisch vom Aufbau sind, jedoch von den Daten leicht differenzieren können.
    Unterschiedliche Datensätze kann ich ja zum Beispiel mit Mengenoperatoren ermitteln.
    Ich möchte jedoch angezeigt bekommen welche Spalten für den Unterschied zuständig sind.
    Händisch, bzw. mit dem Auge zu vergleichen ist zu aufwendig, da es zu viele Spalten gibt.

    Vielen Dank vorab!

  • #2
    Also da musst Du vielleicht etwas spezifischer werden.
    Wieviel Datensätze sind es? Wieviel PK oder FK oder unique Indizes sind drin?
    Oder falls nichts dergleichen, kann man Spalten mit dieser Tendenz ausschließen?
    Kann man anhand von count auf Einzelspalten grobe Unterschiede feststellen?
    Geht es überhaupt um unterschiedliche Datensätze, also Feldwertkombinationen oder um unterschiedliche Spalteninhalte?
    Geht es um leichte Modifikationen oder um starke Differenzen?

    grobes Rezept für unterschiedliche Datensätze:
    a) Tabellen mittels MINUS oder EXCEPT (kommt auf die DB an) voneinander "subtrahieren"
    b) Ist das Ergebnis zu grob, Spalten mit ID Charakter aus dem Vergleich entfernen, wieder a)
    c) Sind für jede Spalte eine hinreichend kleine Menge von unterschiedlichen Werten erreicht (10, 100, 1000, ..), Spalten mit nur einem Wert aus der Menge / Vergleich entfernen.
    d) Spalten in Päärchen, Triple, .. aufteilen und Gruppieren / Zählen, die Kombinationen permutierne, irrelevante Spalten bzw. Gruppen entfernen. wieder d) oder a)

    So irgendwie für den Anfang.

    Wenn Du Spalten mit ID Charakter ab irgendeinem Punkt ausschließen kannst, gruppier bzw. zähle einfach alle restlichen Spalten.
    Falls das Ergebnis der Menge nach nicht mehr gigantisch ist, kannst Du damit sicher auch nette Sachen im Spreadsheet anstellen. Punktwolken oder was weiß ich.
    Gruß, defo

    Comment


    • #3
      Moin �� Danke für deine Hilfe.
      Also die unterschiedlichen Datensätze bekomme ich ermittelt.
      Ich möchte nun wissen, welcher Spalteninhalt dafür verantwortlich ist.

      Angenommen ich ziehe Tabelle 2 von Tabelle 1 ab.
      Jetzt erhalte ich einen Datensatz der übrig bleibt mit 100 Spalten.
      Nun möchte ich aber wissen, welcher Spalteninhalt dafür gesorgt hat, dass minus nicht geklappt hat.

      Ist das möglich? Habe schon ab Subselect in Kombination mit IN gedacht, aber für jede Spalte ist das auch blöd.

      Comment


      • #4
        Originally posted by FlexGer View Post
        Jetzt erhalte ich einen Datensatz der übrig bleibt mit 100 Spalten.
        Nun möchte ich aber wissen, welcher Spalteninhalt dafür gesorgt hat, dass minus nicht geklappt hat.

        Ist das möglich? Habe schon ab Subselect in Kombination mit IN gedacht, aber für jede Spalte ist das auch blöd.
        Nur 1 Datensatz!
        Standard SQL ist ja für Spalteniteration nicht so der Brüller. Wenn die Inhalte (Feldnamen) statisch sind und es also immer um die gleiche Struktur geht, könnte man per Select auf das Oracle Dictionary alle Feldnamen der Tabelle auslesen und als große OR Clause mit ungleichheitsprüfung ausspucken lassen.
        Damit wäre man noch nicht viel weiter, außer dass man wieder auf diesen einen Datensatz kommt.
        Ein 2. Statement über die Columns Liste der Tabelle müsste dann so aufgebaut werden, dass eine Select Clause mit Ungleichheitsprüfung dabei herauskommt. Das Ergebnis der Prüfung als 0/-1; True,/False oderso statt des Feldinhaltes ausspukt.
        Am elegantesten und flexibelsten wäre sicher eine Procedure oder Package Procedure (genauer: Table Function), der man nur 2 Tabellennamen, Viewnamen oder Selectstatements mitgibt und die im Bauch dann automatisiert und dynamisch durch die Feldlisten geht und abgleicht.
        Gruß, defo

        Comment


        • #5
          Okay danke für deine Rückmeldung

          Das ist eine Variante die ich mir überlegt habe als SQL Lösung, aber das ganze für 200 Spalten ist einfach unschön.
          Zu PL/SQL wollte ich jetzt nicht übergehen, damit lässt sich natürlich alles lösen, aber ist dann nun einmal kein reines SQL Statement mehr.

          [highlight=sql]
          with tab1 as
          (select 1 as id, 'a' as spalte1, 'b' as spalte2
          from dual
          union all
          select 1 as id, 'a' as spalte1, 'b' as spalte2
          from dual
          union all
          select 1 as id, 'b' as spalte1, 'b' as spalte2
          from dual
          union all
          select 1 as id, 'h' as spalte1, 'b' as spalte2
          from dual
          union all
          select 1 as id, 'c' as spalte1, 'b' as spalte2
          from dual
          union all
          select 1 as id, 'e' as spalte1, 'b' as spalte2
          from dual
          union all
          select 1 as id, 'f' as spalte1, 'g' as spalte2
          from dual
          union all
          select 1 as id, 'c' as spalte1, 'b' as spalte2
          from dual),
          tab2 as
          (select 1 as id, 'a' as spalte1, 'b' as spalte2
          from dual
          union all
          select 1 as id, 'a' as spalte1, 'b' as spalte2
          from dual
          union all
          select 1 as id, 'b' as spalte1, 'b' as spalte2
          from dual
          union all
          select 1 as id, 'h' as spalte1, 'b' as spalte2
          from dual
          union all
          select 1 as id, 'c' as spalte1, 'b' as spalte2
          from dual
          union all
          select 1 as id, 'i' as spalte1, 'g' as spalte2
          from dual
          union all
          select 1 as id, 'f' as spalte1, 'g' as spalte2
          from dual
          union all
          select 1 as id, 'c' as spalte1, 'b' as spalte2
          from dual),
          daten as
          (select spalte1, spalte2 from tab1 minus select spalte1, spalte2 from tab2)

          select spalte1,
          (select case
          when d.spalte1 in (select spalte1 from tab2) then
          null
          else
          'X'
          end
          from dual) as " ",
          (select 'X'
          from dual
          where not exists (select 'x' from tab2 where spalte1 = d.spalte1)) as " ",
          spalte2,
          (select case
          when d.spalte2 in (select spalte2 from tab2) then
          null
          else
          'X'
          end
          from dual) as " ",
          (select 'X'
          from dual
          where not exists (select 'x' from tab2 where spalte2 = d.spalte2)) as " "
          from daten d
          [/highlight]


          P.S.
          Wo ich schonmal die Profis hier habe, hätte ich noch eine Frage :P
          Gibt es eine Möglichkeit, Spalten beim (*) weg zu lassen (SQL only)?
          Sowas wie...

          [highlight=sql]
          select * except(Spalte9,Spalte10)
          from tabelle
          [/highlight]

          Comment


          • #6
            mmh, also ich hatte eher an sowas gedacht:
            [HIGHLIGHT=SQL]
            -- generate Select clause
            select ' decode(ALIASA.'||column_name||', ALIASB.'||column_name||', ''gleich'', ''ungleich'') as '||column_name||', '
            from user_tab_cols
            where table_name = 'MYTABLE'
            and column_name not in ('ID') -- exclude ID from comparison
            [/HIGHLIGHT]

            Den Select Block dann mit 'SELECT' und From Clause umschließen und fertig. Wie Du die Darstellung im Detail haben willst, kannst Du ja ändern.
            UNd natürlich eine Where Clause anhängen, falls nötig. Oder auch eine generieren lassen.
            Gruß, defo

            Comment


            • #7
              Ja stimmt, so sollte man es realisieren.

              Das SQL wäre ja sowieso nicht dynamisch wenn man Spalten explizit ausgrenzen würde,
              daher kann man das SQL Statement auch generieren lassen, danke.

              Comment


              • #8
                Wie gesagt, kommt auf Einsatzbereich und Wünsche an. Ein paar Exclude Werte mit "not in ('ID', ...)" sind einfach ausgetauscht, den Tablename müsste man ja auch tauschen.
                Und als Tablefunction geht es eleganter und kann besser ausgesteuert werden.
                Gruß, defo

                Comment


                • #9
                  Also die Mengenoperationen werden Dir da nicht viel helfen, weil diese nur nach absolut identischen Mengen schauen. Du kannst einen JOIN ueber beide Tabellen machen und die einzelnen Spalten miteinander vergleichen. So wie es sich fuer mich anhoert gibt es jeweils eine ID in beiden Tabellen die man miteinander verbinden kann.

                  Ich wuerde daher so etwas bauen:

                  [highlight=sql]
                  SELECT t1.id,
                  CASE WHEN t1.wert1 != t2.wert1 THEN 'wert1Unterschied' ELSE 'wert1Gleich' END,
                  CASE WHEN t1.wert2 != t2.wert2 THEN 'wert2Unterschied' ELSE 'wert2Gleich' END,
                  CASE WHEN t1.wert3 != t2.wert3 THEN 'wert3Unterschied' ELSE 'wert3Gleich' END,
                  FROM tabelle1 t1
                  INNER JOIN tabelle2 t2 ON t1.id = t2.id
                  WHERE
                  t1.wert1 != t2.wert1 OR t1.wert2 != t2.wert2 OR t1.wert3 != t2.wert3
                  [/highlight]

                  Natuerlich kannst Du statt der statischen Strings in THEN und ELSE Teil auch eine Berechnung vornehmen oder aehnliches. Prinzipiell sollte das aber das tun was Du willst. Kann nur relativ lang werden wenn man viele Spalten hat. Dynamisch mit Spalten umgehen kann SQL pur soweit ich weiss nicht.

                  Comment


                  • #10
                    Originally posted by fanderlf View Post

                    [highlight=sql]
                    SELECT t1.id,
                    CASE WHEN t1.wert1 != t2.wert1 THEN 'wert1Unterschied' ELSE 'wert1Gleich' END,
                    CASE WHEN t1.wert2 != t2.wert2 THEN 'wert2Unterschied' ELSE 'wert2Gleich' END,
                    CASE WHEN t1.wert3 != t2.wert3 THEN 'wert3Unterschied' ELSE 'wert3Gleich' END,
                    FROM tabelle1 t1
                    INNER JOIN tabelle2 t2 ON t1.id = t2.id
                    WHERE
                    t1.wert1 != t2.wert1 OR t1.wert2 != t2.wert2 OR t1.wert3 != t2.wert3
                    [/highlight]
                    Dynamisch mit Spalten umgehen kann SQL pur soweit ich weiss nicht.
                    Ein Statement, was dieses Vergleichs SQL (Select Clause) produziert, hab ich ja schon oben geschrieben, abgewandelt kann man es auch für die Where Clause ORs einsetzen.
                    Mit Standard SQL wirds umständlich. Oracle bietet aber extra Packages, die es erlauben, SQL dynamisch zusammenzubasteln und zu parsen.
                    Gruß, defo

                    Comment

                    Working...
                    X