Wie bekomme ich nur den exakt passenden Wert aus Tab3. (4 Tabellen)

Hallo zusammen,

da ich mich nach langer langer langer Zeit mal wieder mit SQL beschäftigen muss, habe ich mal eine Frage an euch.

Ich habe eine große Datenbank, as der ich allerdings für meine Abfrage nur 4 Tabellen benötige. request, request_history und business-areas.

Ich benötige folgende Daten:
request: rq_id, fk_ba_id
request_history: die höchste hist_id zum jeweiligen fremdschlüssel fk_rq_id und den zur jewilig höchsten hist_id gehörenden fk_rqs_id
business-areas: den namen der über den fremdschlüssel fk_ba_id aus request verknüpft ist.

Ich möchte also zu einer Anfrage wissen welchem unternehmensbereich sie zugeornet ist, und den aktuellen Status den sie hat. Dazu benötige ich den letzten (höchsten) history-Eintrag und den daraus resultierenden fk_rqs_id.

Zur Zeit versuche ich es so:

SELECT MAX(public.request_history.hist_id), public.request.rq_id, public.business_areas.name, MAX(public.request_history.fk_rqs_id) AS "fk_rqs_id"
FROM ((public.request
INNER JOIN public.business_areas ON public.business_areas.ba_id = public.request.fk_ba_id)
INNER JOIN public.request_history ON public.request_history.fk_rq_id = public.request.rq_id)

WHERE public.request.deleted = false

GROUP BY public.request.rq_id, public.business_areas.name
ORDER BY public.request.rq_id

Ich bekomme FAST die geünschten Ergebnisse. Außer dass ich immer den maximalen Status bekomme, wenn sich der Wert des Status allerdings von 5, auf 4 geändert hat, bekomme ich trotzdem 5. Lasse ich das MAX weg, muss ich den Status in die GROUP BY anweisung nehmen. Dadurch erhalte ich aber jeden Status den eine ANfrage hatte einmal.

Wie bekomme ich es hin, dass ich nur den fk_rqs_id bekomme, der zur höchsten history_id gehört?

Sorry, falls ich mich umständlich ausgedrückt habe. Aber bei Fragen zu meiner Frage helfe ich gerne weiter! :wink:

Grüße
Sandro

Könntest Du bitte, in Code-Tags verpackt, die DDL-Befehle zum Aufbau Deiner Tabellen sowie ein paar Demo-Datensätze liefern? Plus das gewünschte Resultat?
Das würde den Anreiz deutlich erhöhen, Dir zu helfen.

Andreas

Hier ein .zip-File mit den SQL-Skripts zum erzeugen der Tabellen, so wie Backup-Files mit Daten. (Ich habe leider keine Möglichkeit gefunden SQL-Inserts zu generieren, in denen alle Daten enthalten sind. So wie z.B. bei phpMyAdmin.) Wenn man mir diese Möglichkeit sagen könnte, wäre ich sehr froh! Ich hoffe es gibt keine Probleme beim Füllen der Tabellen. :confused:

Das gewünschte Ergebnis wäre:
max_hist_id;rq_id;name;fk_rqs_id
55;70;“E-Business”;1
85;71;“E-Business”;1
76;72;“ERP”;4
100;73;“Systeme & Netze”;5
78;74;“Storage Management”;4
106;75;“Storage Management”;3

Wenn ich mich nicht komplett vertan habe.

Doch, gibt es.

Du kannst COPY benutzen, schau Dir das mal an. Damit kann man ganz simplel eine ASCII-Tei erstellen, die man dann auch wieder einfach einlesen kann.


Okay, ohne es weiter zu testen, aber könntest Du nicht nach Deinem Feld “date” (der timestamp) absteigend sortieren, mit LIMIT auf 1?

Aber, ich geb zu, ich hab nur flüchtig draufgeschaut, hab grad was anderes dringendes zu tun.

Andreas

Danke für die Hilfe mit dem Copy, dass es so einfach geht, hätte ich jetzt nicht gedacht.

Ich habe mal die Demo-Daten in .csv-Dateien kopiert. Hoffe es ist so ok.

Wenn ich nach dem Timestamp ordne und LIMIT auf 1 setze, dann bekomme ich nur einen einzigen Datensatz. (Oder mache ich etwas falsch?)

Ich will aber zu jeder rq_id bei der deleted = false ist, den aktuellsten Status und den Bereich.
Irgendwie bekomme ich das nicht hin. Bin eben doch nicht so erfahren wie manch anderer hier.

Mag sein, ich hab grad weder Zeit noch Lust, das zu testen. Vielleicht später mal.

Wenn ich nach dem Timestamp ordne und LIMIT auf 1 setze, dann bekomme ich nur einen einzigen Datensatz. (Oder mache ich etwas falsch?)

Ich will aber zu jeder rq_id bei der deleted = false ist, den aktuellsten Status und den Bereich.
Irgendwie bekomme ich das nicht hin. Bin eben doch nicht so erfahren wie manch anderer hier.

Okay, scheint ein fall für DISTINCT ON() zu sein:

test=# create table bla (id int, status int);
CREATE TABLE                                 
Zeit: 238,439 ms                             
test=*# copy bla from stdin;
Geben Sie die zu kopierenden Daten ein, gefolgt von einem Zeilenende.
Beenden Sie mit einem Backslash und einem Punkt alleine auf einer Zeile.
>> 1    1
>> 1    3
>> 1    5
>> 2    2
>> 2    1
>> 2    5
>> 3    5
>> 3    3
>> 3    1
>> \.
Zeit: 24099,672 ms
test=*# commit;
COMMIT
Zeit: 0,472 ms
test=# select distinct on (id) id, status from bla order by status desc;
ERROR:  SELECT DISTINCT ON expressions must match initial ORDER BY expressions
test=!# rollback;
ROLLBACK
Zeit: 0,130 ms
test=# select distinct on (id) id, status from bla order by id, status desc;
 id | status
----+--------
  1 |      5
  2 |      5
  3 |      5
(3 Zeilen)

Zeit: 18,643 ms
test=*# select distinct on (id) id, status from bla order by id, status asc;
 id | status
----+--------
  1 |      1
  2 |      1
  3 |      1
(3 Zeilen)

Zeit: 0,258 ms
test=*#

Dieses DISTINCT ON (…) ist eine PG-Erweiterung zum SQL-Standard, Du solltest dazu die Doku befragen, die kennt die Details.


Andreas