tutorials.de Buch-Aktion 05/2012
ERLEDIGT
JA
ANTWORTEN
6
ZUGRIFFE
2418
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Sabine_81 Sabine_81 ist offline Mitglied
    Registriert seit
    Oct 2008
    Beiträge
    11
    Guten Tag,

    ich hätte mal wieder ein Oracle-SQL-Problem und hoffe hier kann mir jemand einen hilfreichen Tipp dazu geben:

    Also folgende Tabellenstruktur hab ich:

    ID___ version___nummer
    1____1________1542
    1____2________ 8185
    2____1________1547

    Anforderung wäre nun folgens:

    ID__älteste_versionsnummer___neueste versionsnummer
    1___1542___________________ 8185
    2___1547___________________ 1547

    Also wenn die Version gleich der maximalen Version für diese ID ist, dann soll der Wert in die eine spalte, wenn die Version gleich der minimalen Version für diese ID ist, dann entsprechend in die zweite.
    Verständlich? jemand ne idee wie man das machen könnte?

    ich hab schon probiert mit
    Code :
    1
    
    where version = min(version)
    aber da bekomme ich den fehler das hier keie agregatfunktion erlaubt sei. mit
    Code :
    1
    2
    3
    4
    5
    
    select id,
    min(version) as a, 
    max(version) as b 
    from tab
    group by id
    bekomme ich die jeweils großte und kleinste version nebeneinander, aber wie kann ich da jetzt die nummer dazu bringen?

    vlg
    Geändert von Sabine_81 (27.10.08 um 14:05 Uhr)
     

  2. #2
    benjava benjava ist offline Mitglied Silber
    Registriert seit
    Oct 2008
    Beiträge
    50
    Hi,
    zuallererst musst du darauf achten, dass jede Kombination aus ID und Version eindeutig ist. Dann kriegst du die passenden Werte zB so raus:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    
    select x.id, minv.nummer as minnummer, maxv.nummer as maxnummer
    from (select id, min(version) as a, max(version) as b
        from tab
        group by id ) as x,
      tab as minv,
      tab as maxv
    where x.id = minv.id and x.a = minv.version
      and x.id = maxv.id and x.b = maxv.version

    Afair ginge es auch mit Hilfe einiger OLAP-Funktionen, aber die hab ich grad nicht im Kopf.
     

  3. #3
    Sabine_81 Sabine_81 ist offline Mitglied
    Registriert seit
    Oct 2008
    Beiträge
    11
    danke schonmal...
    ich habe es jetzt damit probiert... bekomme aber einen fehler: "sql_befehl wurde nicht korekkt beendet" und das "as" nach der klammer wird als falsch angezzeigt. ich hab al testweise mal alle drei "as" weg gelassen, dann bekomme ich den fehler das maxv.version ein ungültiger bezeichner sei...
     

  4. #4
    benjava benjava ist offline Mitglied Silber
    Registriert seit
    Oct 2008
    Beiträge
    50
    oh, stimmt, Oracle mag da kein "as". Aber wenn ich das weglasse, funktionierts bei mir:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    SQL> create table tab( id integer not null, version integer not null, nummer integer not null, primary key( id, version ) );
    SQL> insert into tab values( 1, 1, 1542);
    SQL> insert into tab values( 1, 2, 8185 ); 
    SQL> insert into tab values( 2, 1, 1547 );
     
    SQL> select x.id, minv.nummer as minnr, maxv.nummer as maxnr
      2   from (
      3    select id, min(version) as a, max(version) as b from tab group by id
      4  ) x,
      5  tab minv, tab maxv
      6   where x.id = minv.id and x.a = minv.version
      7    and x.id = maxv.id and x.b = maxv.version;
     
            ID      MINNR      MAXNR
    ---------- ---------- ----------
             1       1542       8185
             2       1547       1547
     

  5. #5
    Sabine_81 Sabine_81 ist offline Mitglied
    Registriert seit
    Oct 2008
    Beiträge
    11
    ohje... ich nehm alles zurück...
    hab "tab" einfach stehen lassen und da nicht den namen meiner tabelle eingetragen... *schäm* sorry...

    also es funktionierts ganz prima

    ganz ganz ganz vielen lieben herzlichen Dank
     

  6. #6
    Avatar von Exceptionfault
    Exceptionfault Exceptionfault ist offline Mitglied Brokat
    Registriert seit
    Sep 2004
    Ort
    Neckarsulm
    Beiträge
    348
    Zu Vollständigkeit hier nochmal eine Lösung mit den Analytischen Funktionen und eine Performancebetrachtung der beiden Lösungen:

    Code sql:
    1
    2
    3
    4
    5
    6
    7
    
    SELECT x.id, minv.nummer AS minnr, maxv.nummer AS maxnr
      FROM (
       SELECT id, MIN(version) AS a, MAX(version) AS b FROM tab GROUP BY id
     ) x,
     tab minv, tab maxv
      WHERE x.id = minv.id AND x.a = minv.version
       AND x.id = maxv.id AND x.b = maxv.version;

    Für diese Lösung berechnet Oracle einen mehr oder weniger komplexen Ausführungsplan und kommt dadurch auf 118 Bytes "Aufwand" und muss 9 Datenblocks lesen.

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    -----------------------------------------------------------------------------
    | Id  | Operation                     | Name         | Rows  | Bytes | Cost |
    -----------------------------------------------------------------------------
    |   0 | SELECT STATEMENT              |              |     2 |   118 |     3|
    |   1 |  NESTED LOOPS                 |              |     2 |   118 |     3|
    |   2 |   NESTED LOOPS                |              |     2 |    98 |     2|
    |   3 |    VIEW                       |              |     2 |    78 |     1|
    |   4 |     HASH GROUP BY             |              |     2 |    12 |     1|
    |   5 |      INDEX FULL SCAN          | SYS_C0063610 |     3 |    18 |     1|
    |   6 |    TABLE ACCESS BY INDEX ROWID| TAB          |     1 |    10 |     1|
    |*  7 |     INDEX UNIQUE SCAN         | SYS_C0063610 |     1 |       |     1|
    |   8 |   TABLE ACCESS BY INDEX ROWID | TAB          |     1 |    10 |     1|
    |*  9 |    INDEX UNIQUE SCAN          | SYS_C0063610 |     1 |       |     1|
    -----------------------------------------------------------------------------
     
    Statistics
    -----------------------------
              9  consistent gets

    Mit analytischen Funktionen würde die Lösung wie folgt aussehen:

    Code sql:
    1
    2
    3
    4
    5
    6
    7
    
    SELECT
        id,
        MIN(nummer) keep (dense_rank FIRST ORDER BY version) AS minnr,
        MAX(nummer) keep (dense_rank LAST ORDER BY version) AS maxnr
    FROM
        tab
    GROUP BY id;

    Der Ausführungsplan ist einfacher und die Performance besser, da nur 2 Blöcke gelesen werden und die "Kosten" nur bei 20 Bytes liegen:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    ----------------------------------------------------------------------------
    | Id  | Operation                    | Name         | Rows  | Bytes | Cost |
    ----------------------------------------------------------------------------
    |   0 | SELECT STATEMENT             |              |     2 |    20 |     1|
    |   1 |  SORT GROUP BY NOSORT        |              |     2 |    20 |     1|
    |   2 |   TABLE ACCESS BY INDEX ROWID| TAB          |     3 |    30 |     1|
    |   3 |    INDEX FULL SCAN           | SYS_C0063610 |     3 |       |     1|
    ----------------------------------------------------------------------------
     
    Statistics
    ----------------------------------------------------------
              2  consistent gets
     
    liebe Grüße
    Exceptionfault (http://exceptionfault.de)

    Never say: "Always"! Always say: "Never say never"! - Tom Kyte @ Ask Tom Live in Berlin 2008

  7. #7
    Sabine_81 Sabine_81 ist offline Mitglied
    Registriert seit
    Oct 2008
    Beiträge
    11
    vielen Dank für den vergleich. ich habe die zweite Version auch mal ausprobiert, funktioniert auch sehr gut.
    da es bei mir im moment nicht sehr viele datensätze gibt, bemerke ich perfomancemässig aber aktuell keinen unterschied. aber prima, dass ich diese version jetzt auch noch kenne :-D
     

Ähnliche Themen

  1. Selektion eines nicht belegten Wertes innerhalb eines Bereiches (Oracle 10g)
    Von TimoTH im Forum Relationale Datenbanksysteme
    Antworten: 2
    Letzter Beitrag: 06.10.10, 16:42
  2. Konstruktor mit Übergabe eines Wertes
    Von voelzi im Forum C/C++
    Antworten: 1
    Letzter Beitrag: 21.11.09, 21:05
  3. Antworten: 1
    Letzter Beitrag: 26.06.08, 12:41
  4. Übergabe eines Wertes
    Von minlok im Forum .NET Archiv
    Antworten: 0
    Letzter Beitrag: 17.03.05, 09:54
  5. Ausdruck eines Wertes bei Anlegen eines neuen Datensatzes
    Von realmontanakid im Forum .NET Archiv
    Antworten: 3
    Letzter Beitrag: 19.10.04, 11:02