Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

SELECT TOP 1 ... aus mehreren Gruppierten Wertereihen einer Tabelle

Dieses Thema im Forum "Microsoft SQL Server" wurde erstellt von Catweazle4ever, 1 Juli 2013.

  1. Catweazle4ever

    Catweazle4ever Neuer Benutzer

    Hallo,

    ich beschäftige mich erst seit kurzem intensiver mit SQL und taste mich so langsam an die Abfrage-Syntax heran. Jetzt versuche ich gerade aus einer Tabelle eindeutige Werte herauszubekommen aber scheitere damit.

    Vielleicht könnt ihr mir dabei helfen und den richtigen Request aufzeigen.

    Code:
    Tabelle tab_xyz (vereinfacht)
     
    job_id insert_time          percentage  period_start          period_end
    ============================================================================================
    17    2013-06-30 07:07:00  98.04        2013-06-29 00:00:00  2013-06-30 00:00:00
    13    2013-06-30 06:13:00  96.57        2013-06-29 00:00:00  2013-06-30 00:00:00
    25    2013-06-30 08:12:00  99.74        2013-06-29 00:00:00  2013-06-30 00:00:00
    12    2013-06-29 06:13:00  92.96        2013-06-28 00:00:00  2013-06-29 00:00:00
    10    2013-06-28 06:13:00  94.12        2013-06-27 00:00:00  2013-06-28 00:00:00
    11    2013-06-27 06:13:00  99.23        2013-06-26 00:00:00  2013-06-27 00:00:00
     
    als Ergbenis sollte dann nur folgende Zeilen herauskommen (sortiert nach insert_time):
     
    job_id insert_time          percentage  period_start          period_end
    ============================================================================================
    25    2013-06-30 08:12:00  99.74        2013-06-29 00:00:00  2013-06-30 00:00:00
    12    2013-06-29 06:13:00  92.96        2013-06-28 00:00:00  2013-06-29 00:00:00
    10    2013-06-28 06:13:00  94.12        2013-06-27 00:00:00  2013-06-28 00:00:00
    11    2013-06-27 06:13:00  99.23        2013-06-26 00:00:00  2013-06-27 00:00:00
    
    Ich habe es schon mit einem Subquerie probiert, komme damit aber nicht zu gewünschten Ergebnis:


    Code:
    select * from tab_xyz
    where job_id in
        (select top 1 job_id from tab_xyz
        order by period_start DESC, insert_time DESC)
    Damit bekomme ich aber nur die Zeile mit der job_id = 25 zurück und nicht die Zeilen mit anderen period_start-Werten.

    Wie müsste der richtige Request aussehen.

    Vielen Dank
     
  2. akretschmer

    akretschmer Datenbank-Guru

    Ich scheitere damit, die Frage zu verstehen. Das liegt u.a. auch daran, daß Du keine passende Code-Darstellung hast, verwende bitte passende Formatierungen.
    Was verstehst Du unter eindeutig in Deinen Daten?
     
  3. ukulele

    ukulele Datenbank-Guru

    Er möchte scheinbar nach period_start aggregieren und dazu immer den Datensartz mit der höchsten insert_time ausgeben. Ich hab es nicht getestet aber so in etwa könnte es gehen, vieleicht auch noch etwas schlanker :) :
    Code:
    SELECT    t2.job_id,
            t1.insert_time,
            t2.percentage,
            t1.period_start,
            t1.period_end
    FROM    (    SELECT    period_start,
                        period_end,
                        max(insert_time) AS insert_time
                FROM    tabelle
                GROUP BY period_start,period_end ) t1
    LEFT JOIN tabelle t2
    ON        t2.period_start = t1.period_start
    AND        t2.period_end = t1.period_end
    AND        t2.insert_time = t1.insert_time
    ORDER BY t1.period_start DESC
     
    Catweazle4ever gefällt das.
  4. Catweazle4ever

    Catweazle4ever Neuer Benutzer

    @all - erst einmal vielen Dank für die schnellen Antworten...

    Sorry, hatte heute morgen (war im Zug unterwegs) übersehen, wo man den Code-Modus einschalten kann. Ich habe das jetzt im Original-Post gerade nachgeholt.

    @ukulele - ja, genau das möchte ich habe. Ich konnte es nur so schön nicht ausrücken ;-)

    Wenn ich wieder zu Hause bin teste ich dein Query mal.
     
  5. akretschmer

    akretschmer Datenbank-Guru


    In PostgreSQL gibt es DISTINCT ON(), mit dem man das elegant machen könnte, ist aber nicht Teil der SQLSpec und gibt es vermutlich in M$SQL nicht.
    http://www.postgresql.org/docs/9.2/static/sql-select.html#SQL-DISTINCT
     
  6. Catweazle4ever

    Catweazle4ever Neuer Benutzer

    Hallo ukulele,

    dein Query liefert genau das Ergebnis zurück, das ich haben will. Vielen Dank.
    Ich habe mir den Query aber einfacher vorgestellt. Mit meinem aktuellen SQL-KnowHow wäre ich da nie drauf gekommen. Muss mich wohl mal mehr um die JOINs und APPLYs kümmern. Gibt es denn im Netz ein gutes Tutorial oder ein gutes SQL-Wiki mit dem man sein SQL-Wissen aufbauen und vertiefen kann?

    @akretschmer: DISTINCT ON() hört sich gut an - aber habe ich tatsächlich unter MS-SQL nicht gefunden.
     
  7. akretschmer

    akretschmer Datenbank-Guru

    Laut ukulele, Zitat: "Er möchte scheinbar nach period_start aggregieren und dazu immer den Datensartz mit der höchsten insert_time ausgeben.", sollte auch gehen, vereinfacht:

    select * from (select ..., row_number() over (partition by period_start order by insert_time desc) as c) foo where c=1

    Also, unterteilt nach period_start abwärts nach insert_time zählen und je period_start nur den ersten nehmen. Das sollte auch mit M$SQL gehen.
     
  8. ukulele

    ukulele Datenbank-Guru

    Ich muss gestehen PARTITION BY habe ich noch nicht genutzt aber sieht so aus als könnte MSSQL das. Ich könnte mir auch vorstellen das es ohne einen einfacheren Weg mit HAVING gibt aber mir schien das der einfachste Weg mit minimaler SQL Syntax. Klar ist das man gruppieren muss und da ich dieverse Werte wie percentage durch die Gruppierung nicht ausgeben kann muss ich sie später wieder dazu joinen.
     
  9. akretschmer

    akretschmer Datenbank-Guru

    Schau es Dir an, das ist ganz wesentlich bei Window-Funktionen, also bei sehr vielen analytischen Auswertungen.
     
    Catweazle4ever gefällt das.
  10. Catweazle4ever

    Catweazle4ever Neuer Benutzer

    Hallo,

    ich habe mir gerade mal das PARTITION BY angeschaut. Das sieht ja richtig gut aus und funktioniert sogar. Mit dem Request
    Code:
    SELECT job_id,insert_time,percentage,period_start,period_end
    FROM  ( SELECT *,ROW_NUMBER() OVER (PARTITION BY period_start ORDER BY insert_time DESC) AS c
            FROM tab_xyz ) foo
    WHERE  c=1
    ORDER  BY period_start DESC
    bekomme ich auch das gewünschte Ergebnis.

    Super - das sieht ja um einiges einfacher aus und ist wahrscheinlich auch noch performanter.

    Danke
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden