Select neuster datensatz bei drei Tabellen

chzhtg

Neuer Benutzer
Beiträge
4
Hallo

Ich benötige von allen Personen den letzten Arbeitsschritt. Mit MAX(t_t3.reihenfolge) as reihenfolge bekomme zwar die Reihenfolge, aber das Datum nicht richtig

Wie bekomme ich den neusten Eintrag, letzter Datensastz von t2 mit der richtigen Bezeichnung? Es kommt immer der erste Eintrag, statt der letzte, und schlussendlch sollte das Ganze nach Namen sortiert sein.



3 Tabellen
t1 personendaten
t2 einzelne Arbeitsschritte (Datum, Id der Bezeichnung)
t3 Definition der Arbeitsschritte (Bezeichnung, Reihenfolge)


SELECT t_t1.id_t1,t_t1.tfname, MAX(t_t2.id_t2) as id_t2, t_t2.datum_t2,t_t2.datum_termin,t_t2.datum_antwort,t_t3.einzelschritt,MAX(t_t3.reihenfolge) as reihenfolge
FROM `t_t1`
left join t_t2 on t_t1.id_t1=t_t2.id_t1
left join t_t3 on t_t2.id_einzelschritt=t_t3.id_t3
group by t_t1.id_t1
ORDER BY `t_t1`.`tfname` ASC

Stehe auf dem schlauch, es geht nicht, wie bekomme ich zum Namen den neusten Datensatz aus t2 mit der Bezeichnung von t3?

Danke
 
Werbung:
Ohne die Tabellenstrukturen und deren Beziehungen untereinander zu kennen wird es schwer, Dir zu helfen. Aber eines ist schon sichtbar: Du aggregierst 2 Spalten (max()-Funktion, und hast 6 weitere Spalten, aber nur nach einer von diesen gruppiert. Das ist logisch falsch und würde von 'richtigen' Datenbanken als Fehler erkannt werden. MySQL liefert statt einer Fehlermeldung ein zufälliges Resultat.
 
ich hab mal versucht zu erraten, was Du da hast:

Code:
edb=*> \d personen
              Table "public.personen"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 p_id   | integer |           | not null |
 name   | text    |           |          |
Indexes:
    "personen_pkey" PRIMARY KEY, btree (p_id)
Referenced by:
    TABLE "arbeiten" CONSTRAINT "arbeiten_wer_fkey" FOREIGN KEY (wer) REFERENCES personen(p_id)

edb=*> \d arbeitsschritte
             Table "public.arbeitsschritte"
   Column    |  Type   | Collation | Nullable | Default
-------------+---------+-----------+----------+---------
 id          | integer |           | not null |
 bezeichnung | text    |           |          |
 reihenfolge | integer |           |          |
Indexes:
    "arbeitsschritte_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "arbeiten" CONSTRAINT "arbeiten_schritt_fkey" FOREIGN KEY (schritt) REFERENCES arbeitsschritte(id)

edb=*> \d arbeiten
                        Table "public.arbeiten"
 Column  |            Type             | Collation | Nullable | Default
---------+-----------------------------+-----------+----------+---------
 id      | integer                     |           | not null |
 wer     | integer                     |           |          |
 datum   | timestamp without time zone |           |          |
 schritt | integer                     |           |          |
Indexes:
    "arbeiten_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "arbeiten_schritt_fkey" FOREIGN KEY (schritt) REFERENCES arbeitsschritte(id)
    "arbeiten_wer_fkey" FOREIGN KEY (wer) REFERENCES personen(p_id)

edb=*>

Dazu folgende Daten:

Code:
edb=*> select * from personen ;
 p_id |   name   
------+----------
    1 | Person 1
    2 | Person 2
(2 rows)

edb=*> select * from arbeitsschritte ;
 id | bezeichnung | reihenfolge
----+-------------+-------------
  1 | Schritt 1   |          10
  2 | Schritt 2   |          20
  3 | Schritt 3   |          30
(3 rows)

edb=*> select * from arbeiten ;
 id | wer |       datum        | schritt
----+-----+--------------------+---------
  1 |   1 | 01-JAN-21 00:00:00 |       1
  2 |   1 | 02-JAN-21 00:00:00 |       2
  3 |   1 | 03-JAN-21 00:00:00 |       3
  4 |   2 | 01-FEB-21 00:00:00 |       1
  5 |   2 | 02-FEB-21 00:00:00 |       2
(5 rows)

edb=*>


Was Du suchst ist nun offenbar:

Code:
edb=*> with tmp as (select wer, max(datum) as datum from arbeiten group by wer) select tmp.datum, p.name, s.bezeichnung from tmp left join personen p on tmp.wer=p.p_id left join arbeiten a on ((tmp.wer, tmp.datum)=(a.wer,a.datum)) left join arbeitsschritte as s on a.schritt=s.id;
       datum        |   name   | bezeichnung
--------------------+----------+-------------
 03-JAN-21 00:00:00 | Person 1 | Schritt 3
 02-FEB-21 00:00:00 | Person 2 | Schritt 2
(2 rows)

edb=*>

Die Reihenfolge in der Tabelle 'arbeitsschritte' habe ich hier nicht verwendet, da ich davon ausgehe, daß beim Insert der Daten sichergestellt wird, daß die Arbeiten in der korrekten Reihenfolge erfaßt werden.
 
Danke akretschmer, das ist was ich suche

Ich habe deinen Code eigentlich verstanden, kann es aber nicht reproduzieren. Was ist nicht verstehe ist edb=*> Google kann mir da auch nicht helfen.

Ich verstehe eigentlich, was du mir vorschlägst: zuerst eine tmp-Selektion zu machen. Ich versuchte es in phpMyAdmin nachzuvollziehen, doch es geht nicht.

Deine Interpretaion der Tabellen stimmt, habe es mit deinen Bezeichnungen nachvollzogen.


SELECT person.*,arbeiten.*,arbeitsschritte.*,FROM_UNIXTIME(arbeiten.datum,'%d.%m.%Y') as datum FROM `arbeiten`
left join person on person.p_id=arbeiten.wer
left join arbeitsschritte on arbeiten.schritt=arbeitsschritte.id
ORDER BY `person`.`name` DESC

ergibt

p_id | name | id | wer | schritt | datum | id | bezeichnung | reihenfolge | datum
29 | Wanner | 85 | 29 | 3 | 1581894000 | 3 | Sonderprivat | 115 | 17.02.2020
29 | Wanner | 84 | 29 | 1 | 1460412000 | 1 | Ersterf. | 5 | 12.04.2016
29 | Wanner | 86 | 29 | 7 | 1463436000 | 7 | Erstgespräch | 25 | 17.05.2016
28 | Voss | 83 | 28 | 7 | 1589925600 | 7 | Erstgespräch | 25 | 20.05.2020
28 | Voss | 82 | 28 | 3 | 1591048800 | 3 | Sonderprivat | 115 | 02.06.2020
28 | Voss | 81 | 28 | 1 | 1589148000 | 1 | Ersterfassung | 5 | 11.05.2020
27 | Stössel | 80 | 27 | 3 | 1581980400 | 3 | Sonderprivat | 115 | 18.02.2020
27 | Stössel | 79 | 27 | 7 | 1393282800 | 7 | Erstgespräch | 25 | 25.02.2014
27 | Stössel | 78 | 27 | 1 | 1391727600 | 1 | Ersterfassung | 5 | 07.02.2014
26 | Schweizer | 120 | 26 | 20 | 1603963255 | 20 | Kündigung | 215 | 29.10.2020
26 | Schweizer | 77 | 26 | 7 | 1428962400 | 7 | Erstgespräch | 25 | 14.04.2015
26 | Schweizer | 76 | 26 | 1 | 1428357600 | 1 | Ersterfassung | 5 | 07.04.2015
26 | Schweizer | 102 | 26 | 32 | 1602745706 | 32 | Arbeitsvertr | 150 | 15.10.2020

Ich brauche jedoch nur
p_id | name | id | wer | schritt | datum | id | bezeichnung | reihenfolge | datum
29 | Wanner | 85 | 29 | 3 | 1581894000 | 3 | Sonderprivat | 115 | 17.02.2020
28 | Voss | 82 | 28 | 3 | 1591048800 | 3 | Sonderprivat | 115 | 02.06.2020
27 | Stössel | 80 | 27 | 3 | 1581980400 | 3 | Sonderprivat | 115 | 18.02.2020
26 | Schweizer | 120 | 26 | 20 | 1603963255 | 20 | Kündigung | 215 | 29.10.2020

Wie kann ich in PHP oder PhpMyadmon eine vorgängige tmp-Abrefe machen?

Danke für die Hilfe. Würde dir auch gerne ein Bier ausgeben, wenn es wieder geht und ich aus dem tiefen Süden im shönen Dresden wäre
 
Was ist nicht verstehe ist edb=*>

Das ist der Prompt der Datenbank. Ich verwende:

Code:
edb=*> select version();
                                                                               version                                                                               
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 13.1 (EnterpriseDB Advanced Server 13.1.4 (Ubuntu 13.1.4-1+ubuntu4)) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0, 64-bit
(1 row)

Dein Fehler im Select ist, daß Du von Deiner "arbeiten" - Tabelle alle Einträge abfragst und nicht via Aggregation/Gruppierung das auf den aktuellsten Datensatz je Mitarbeiter eingrenzt. Die von mir verwendete Syntax nennt sich CTE (Common Table Expressions), was MySQL aber wohl auch nicht kann. Man kann das aber umstellen, etwa select ... from (select wer, max(datum) from ...) as tmp ... und die anderen Tabellen dranjoinen.
 
Vielen Dank, es klappte bestens.

Wieso es auf dem Testserver, ein XAMPP, nicht geht, jedoch online beim Provider bestens, brachte mich zum Verzeifeln und muss ich separat klären.

in PhpMyAdmin konnte ich den vorgeschlagenen Code als SQL erfassen. Danke für die Unterstützung

with tmp as (select wer, max(datum) as datum from arbeiten group by wer)
select tmp.datum, p.name, s.bezeichnung from tmp
left join person p on tmp.wer=p.p_id
left join arbeiten a on ((tmp.wer, tmp.datum)=(a.wer,a.datum))
left join arbeitsschritte as s on a.schritt=s.id
 
Werbung:
Zurück
Oben