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 neuster datensatz bei drei Tabellen

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von chzhtg, 13 Februar 2021.

  1. chzhtg

    chzhtg Neuer Benutzer

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

    akretschmer Datenbank-Guru

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

    akretschmer Datenbank-Guru

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

    chzhtg Neuer Benutzer

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

    akretschmer Datenbank-Guru

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

    Walter Administrator Mitarbeiter

  7. chzhtg

    chzhtg Neuer Benutzer

    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
     
    akretschmer gefällt das.
  8. akretschmer

    akretschmer Datenbank-Guru

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