Announcement

Collapse
No announcement yet.

Drei Tabellen vermischen, aber wie?

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

  • Drei Tabellen vermischen, aber wie?

    Hallo, ich habe schon ewig rumprobiert, aber ich komm' zu keiner vernünftigen Lösung. Hier mein Problem:

    ich habe 3 Tabellen und will diese zu einer Tabelle zusammenfassen.

    TAB1
    -------
    KUNDNR GRUND BEGINN ENDE
    0815 A leer 25.03.2008
    0815 A 01.12.2001 01.12.9999
    0815 B 20.01.2000 25.01.2003
    0817 C 20.01.2003 26.01.2003


    TAB2
    ------
    KUNDNR GRUND BEGINN ENDE
    0816 B 20.01.2003 25.01.2003
    0817 A 01.12.2001 leer
    0817 C 19.01.2003 25.01.2003

    TAB3
    ------
    KUNDNR GRUND BEGINN ENDE
    0815 A 20.08.2006 31.12.9999
    0815 B 01.12.2001 01.12.9999
    0816 C 19.01.2005 25.01.2006


    Die Zieltabelle sollte dann wie folgt aussehen:

    ZIELTAB
    ---------
    KUNDNR GRUND MIN(BEGINN) MAX(ENDE)
    0815 A leer 31.12.9999
    0815 B 20.01.2000 01.12.9999
    0816 B 20.01.2003 25.01.2003
    0816 C 19.01.2005 25.01.2006
    0817 A 01.12.2001 leer
    0817 C 19.01.2003 26.01.2003

    Ich möchte in der Zieltabelle jeweils die KUNDR und einen(!) GRUND haben mit dem Minimum(BEGINN) und dem Maximum(ENDE) aller Einträge mit diesem Grund. Ist kein BEGINN und/oder ENDE gesetzt ("leer") ist dieses das Minimum bzw. das Maximum.

    Ich hoffe ich habe mich verständlich ausgedrückt und eine/r kann mir helfen.

    Danke im Voraus!

    Jungspund

  • #2
    Warum sind die Sätze eigentlich in drei unterschiedlichen Tabellen? Na egal, ich habe die Tabellen mit WITH simuliert und als erste Näherung:
    Code:
    WITH 
    tab1 AS (
       SELECT '0815' kundnr, 'A' grund, NULL                               beginn, to_date('25.03.2008','DD.MM.YYYY') ende FROM dual UNION ALL
       SELECT '0815' kundnr, 'A' grund, to_date('01.12.2001','DD.MM.YYYY') beginn, to_date('01.12.9999','DD.MM.YYYY') ende FROM dual UNION ALL
       SELECT '0815' kundnr, 'B' grund, to_date('20.01.2001','DD.MM.YYYY') beginn, to_date('25.01.2003','DD.MM.YYYY') ende FROM dual UNION ALL
       SELECT '0817' kundnr, 'C' grund, to_date('20.01.2003','DD.MM.YYYY') beginn, to_date('26.01.2003','DD.MM.YYYY') ende FROM dual
     ),
    tab2 AS (
       SELECT '0816' kundnr, 'B' grund, to_date('20.01.2003','DD.MM.YYYY') beginn, to_date('25.01.2003','DD.MM.YYYY') ende FROM dual UNION ALL
       SELECT '0817' kundnr, 'A' grund, to_date('01.12.2001','DD.MM.YYYY') beginn, null                               ende FROM dual UNION ALL
       SELECT '0817' kundnr, 'C' grund, to_date('19.01.2003','DD.MM.YYYY') beginn, to_date('25.01.2003','DD.MM.YYYY') ende FROM dual 
     ),
    tab3 AS (
       SELECT '0815' kundnr, 'A' grund, to_date('20.08.2006','DD.MM.YYYY') beginn, to_date('31.12.9999','DD.MM.YYYY') ende FROM dual UNION ALL
       SELECT '0815' kundnr, 'B' grund, to_date('01.12.2001','DD.MM.YYYY') beginn, to_date('01.12.9999','DD.MM.YYYY') ende FROM dual UNION ALL
       SELECT '0816' kundnr, 'C' grund, to_date('19.01.2005','DD.MM.YYYY') beginn, to_date('25.01.2006','DD.MM.YYYY') ende FROM dual 
     )
    SELECT kundnr, grund, min(beginn), max(ende)  FROM
    (
      SELECT * FROM tab1
      UNION ALL
      SELECT * FROM tab2
      UNION ALL
      SELECT * FROM tab3
    ) GROUP BY kundnr, grund 
      ORDER BY kundnr, grund 
    
    KUNDNR	GRUND	MIN(BEGINN)	MAX(ENDE)
    ------------------------------------------------------------------
    0815	A	01.12.2001	31.12.9999
    0815	B	20.01.2001	01.12.9999
    0816	B	20.01.2003	25.01.2003
    0816	C	19.01.2005	25.01.2006
    0817	A	01.12.2001	
    0817	C	19.01.2003	26.01.2003
    Hier muss nur noch die Behandlung der leeren Sätze eingebaut werden, steht da tatsächlich "leer" drin ?!
    Das würde bedeuten, es handelt sich nicht um Datumsfelder. Damit wird das Sortieren komplizierter:
    Code:
    DATUM  '05.02.2010'>'30.01.2010' 
    TEXT   '05.02.2010'<'30.01.2010'
    Viel Erfolg!

    Comment


    • #3
      [highlight=sql]
      select allTabs.kundnr, grund, min(nvl(allTabs.beginn,to_date('01.01.1900','dd.mm .yyyy'))),max(nvl(allTabs.ende,to_date('31.12.2100 ','dd.mm.yyyy')))
      from
      (
      SELECT * FROM tab1
      union all
      SELECT * FROM tab2
      union all
      SELECT * FROM tab3
      ) as allTabs
      group by kundnr, grund
      order by kundnr, grund
      [/highlight]

      Die 2 Datumsangaben stellen jeweils das Minimum und Maximum Datum dar. Ich weiss nicht ob MIN und MAX Null werte mit Auswerten.

      Edit: Da war jemand schneller
      Zuletzt editiert von fanderlf; 05.02.2010, 15:57.

      Comment


      • #4
        Hallo,

        auch noch eine Variante von mir (ich habe mal 0817 C auch noch eine NULL-Ende gegeben, damit es nicht zu einfach wird ;-)

        Code:
        WITH a AS (
          SELECT '0815' kundennr, 'A' grund,NULL beginn, TO_DATE('25.03.2008','dd.mm.yyyy') ende FROM dual
          UNION ALL
        SELECT '0815','A',to_date('01.12.2001','dd.mm.yyyy'),to_date('01.12.9999','dd.mm.yyyy') from dual
          union all
        SELECT '0815','B',to_date('20.01.2000','dd.mm.yyyy'),to_date('25.01.2003','dd.mm.yyyy') from dual
          union all
        SELECT '0817','C',to_date('20.01.2003','dd.mm.yyyy'),to_date(NULL,'dd.mm.yyyy') from dual)
         ,b AS (
          SELECT '0816' kundennr,'B' grund,to_date('20.01.2003','dd.mm.yyyy') beginn,to_date('25.01.2003','dd.mm.yyyy') ende from dual
          union all
        SELECT '0817','A',to_date('01.12.2001','dd.mm.yyyy'),to_date(NULL,'dd.mm.yyyy') from dual
          union all
        SELECT '0817','C',to_date('19.01.2003','dd.mm.yyyy'),to_date('25.01.2003','dd.mm.yyyy') from dual)
         ,c AS (
        SELECT '0815' kundennr,'A' grund,to_date('20.08.2006','dd.mm.yyyy') beginn,to_date('31.12.9999','dd.mm.yyyy') ende from dual
          union all
        SELECT '0815','B',to_date('01.12.2001','dd.mm.yyyy'),to_date('01.12.9999','dd.mm.yyyy') from dual
          union all
        SELECT '0816','C',to_date('19.01.2005','dd.mm.yyyy'),to_date('25.01.2006','dd.mm.yyyy') from dual)
        , d AS (SELECT * FROM a 
                UNION ALL
                SELECT * FROM b
                UNION ALL
                SELECT * FROM c)
        , e AS (SELECT kundennr
                      ,grund
              ,first_value(beginn) OVER (PARTITION BY kundennr,grund ORDER BY beginn nulls FIRST) fb 
              ,first_value(ende) OVER (PARTITION BY kundennr,grund ORDER BY ende DESC nulls first) fe 
                FROM d )
        SELECT kundennr
              ,grund
              ,MIN(fb) beginn
              ,MIN(fe) ende
        FROM e
        GROUP BY kundennr,grund
        ORDER BY kundennr, grund;
        
        KUND G BEGINN   ENDE
        0815 A          31.12.99
        0815 B 20.01.00 01.12.99
        0816 B 20.01.03 25.01.03
        0816 C 19.01.05 25.01.06
        0817 A 01.12.01
        0817 C 19.01.03 
        
        6 Zeilen ausgewählt.
        Schönes Wochenende alle miteinander

        Ralf

        Comment


        • #5
          Vielen lieben Dank! Funktioniert perfekt!
          Ihr habt mich gerettet ;-)
          Da wäre ich so nie drauf gekommen.

          Eine (Verständnis)Fragen hätte ich trotzdem noch:

          1. Ich habe ein sehr großen Select mit vielen Subselects. Jetzt kriege ich jedoch die Fehlermeldung, dass ein Subselect zu viele Ergebnisse zurückliefert. Wie kriege ich raus, welcher Subselect die Fehlermedlung erzeugt? (Bislang bin ich nach der Methode "Try&Error" vorgegangen und habe jeden einzelnen Subselect für sich geprüft. Die Methode finde ich aber sehr mühsam...)

          Comment


          • #6
            hmm... ich würde mal anfangen zu suchen, welches SubSelect denn evtl. mehr als eine Zeile zurück gibt, obwohl es nur eine Zeile zurückgeben dürfte. Ich vermute dass es wohl darum geht. Was anderes als "Try & Error" fällt mir aber auch nicht ein.

            Comment


            • #7
              Poste doch deinen Quellcode.

              Enthält die SELECT-Klausel deines Subselects eine Gruppenfunktion, so wird nur ein Datensatz geliefert, wenn im Subselect nur Daten einer Gruppe enthalten sind. Dies ist beispielsweise bei korrellierenden Unterabfragen der Fall.

              @fanderlf:
              MIN und MAX gehören zu den Gruppenfunktionen. Gruppenfunktionen ignorieren NULL-Werte.


              kuemmelchen

              Comment


              • #8
                Hier meine Abfrage:

                SELECT *
                FROM
                'SUBSELECT1',
                'SUBSELECT2',
                'SUBSELECT3',
                ....
                CASE WHEN EXISTS
                (SELECT MAX(1) KEEP (DENSE_RANK FIRST ORDER BY s.iz_aktual_ts, s.iz_beginn DESC)
                FROM T_PP_STAT s
                WHERE s.IZ_PP_NR = 1234)
                THEN 'J'
                ELSE 'N'
                END,

                'SUBSELECT5',
                'SUBSELECT6',
                'SUBSELECT7'
                FROM ....;


                Für mich ist es einfach nicht nachvollziehbar, warum ich bei "DENSE_RANK FIRST" noch eine Gruppenfunktion anwenden muss. Es ist doch von vornherein klar, dass keiner oder nur ein Satz zurückgeliefert wird. Naja, ich nehm' es jetzt einfach mal als "gegeben" hin. Logisch ist es aber nicht! Gruß Jungspund!

                Comment


                • #9
                  Dein Quellcode ist (vermutlich beim Vereinfachen passiert) syntaktisch falsch und das Problem daher für mich nicht nachvollziehbar:
                  Code:
                  --wieso stehen die SUBSELECTS in Anführungszeichen
                  -->  ORA-00903: Ungültiger Tabellenname
                  SELECT * FROM 'SUBSELECT1'
                  
                  --hier fehlt irgendwo ein SELECT
                  --> ORA-00933: SQL-Befehl wurde nicht korrekt beendet
                  SELECT * FROM 'SUBSELECT1',... 'SUBSELECT7' FROM ...

                  Comment


                  • #10
                    dieser Select dient natürlich nur als Veranschaulichung.

                    Wichtig ist hier nur dieser Subselect
                    ...
                    CASE WHEN EXISTS
                    (SELECT MAX(1) KEEP (DENSE_RANK FIRST ORDER BY s.iz_aktual_ts, s.iz_beginn DESC)
                    FROM T_PP_STAT s
                    WHERE s.IZ_PP_NR = 1234)
                    THEN 'J'
                    ELSE 'N'
                    END,
                    ...

                    Warum muss ich hier eine Gruppenfunktion (MAX) anwenden, wenn von vorherein klar ist, dass nur ein Satz zurückgeliefert wird?

                    Comment

                    Working...
                    X