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

Catweazle4ever

Neuer Benutzer
Beiträge
4
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
 
Werbung:
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.

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?
 
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
 
@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.
 
@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.


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
 
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.
 
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.

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.
 
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.
 
Werbung:
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
 
Zurück
Oben