JOIN mit Bedingung?

TheRealBllue

Neuer Benutzer
Beiträge
3
Hallo zusammen,

ich habe eine kleine Seite zum Verwalten von Feuerlöschern gebaut.

Jeder Feuerlöscher ist mit all seinen Daten in der einen Tabelle hinterlegt.
Die zugehörigen wiederkehrenden Prüfungen werden mit der ID des Löschers dem Grund der Prüfung, dem jeweiligen Datum der Prüfung und dem Datum der nächsten Prüfung in einer separaten Tabelle gespeichert um eine Historie zu behalten.

Ich möchte mir jetzt anzeigen lassen, welche Löscher in den nächsten 3 Monaten geprüft werden müssen bzw. schon überfällig sind und an welchem Standort diese stehen. Grundsätzlich bekomme ich die Ausgabe aller aktuellen "Ablaufdaten" über einen JOIN mit GROUP BY loescher_id und MAX(ablaufdatum) hin. Aber dann kann ich die Bedingung mit "Muss geprüft werden" nicht mehr abfragen.

Hier die CREATE TABLEs

CREATE TABLE `feuerloescher` (
`id` int(4) NOT NULL,
`barcode` varchar(8) NOT NULL,
`art` varchar(10) NOT NULL,
`standort` varchar(35) NOT NULL,
`abteilung` int(3) NOT NULL,
`zustand` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



CREATE TABLE `loescher_pruefungen` (
`id` int(6) NOT NULL,
`loescher_id` int(4) NOT NULL,
`pruefdatum` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ablaufdatum` date NOT NULL,
`pruefgrund` varchar(25) NOT NULL,
`ergebnis` varchar(25) NOT NULL,
`pruefer` varchar(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Kann mir jemand helfen?
Danke im voraus!

Beste Grüße
Yannik
 
Werbung:

akretschmer

Datenbank-Guru
Beiträge
9.848
Was hast Du denn schon versucht? Und warum verwendest Du keine Primary Keys / Foreign Keys? Und warum varchar für Barcode, dafür gibt es doch passende Datentypen?
Ach ne, Datentypen für Barcodes gibt es nicht in MySQL ...
 

akretschmer

Datenbank-Guru
Beiträge
9.848
um deine Frage grundlegend zu beantworten: Du kannst Bedingungen in das JOIN einbauen oder noch ein Where verwenden. Bedingung im JOIN:

Code:
edb=*# create table master (id int primary key, name text);
CREATE TABLE
edb=*# create table detail (id int primary key, master_id int references master, val int);
CREATE TABLE
edb=*# select * from master left join detail on master.id = detail.master_id and detail.val between 1 and 5;
 id | name | id | master_id | val
----+------+----+-----------+-----
(0 rows)

edb=*#

Das in Deine geheime Abfrage einzubauen überlasse ich Dir zur Übung.
 

TheRealBllue

Neuer Benutzer
Beiträge
3
Hallo ihr beiden,

zunächst: Bei beiden Tabellen ist die Spalte id Primary Key, das steht erst weiter unten in meinem Struktur Export.

Bisher hole ich mir die jeweils letzten Verfalldaten über folgende Abfrage:

$res = $db->prepare("
SELECT
feuerloescher.standort, feuerloescher.barcode, loescher_pruefungen.loescher_id, MAX(loescher_pruefungen.ablaufdatum) AS ablaufdatum
FROM
loescher_pruefungen
LEFT JOIN
feuerloescher ON (feuerloescher.id = loescher_pruefungen.loescher_id)
GROUP BY
loescher_pruefungen.loescher_id
ORDER BY
ablaufdatum desc
");

Versuche das jetzt zu "Muss in 3 Monaten geprüft werden oder ist schon überfällig" zu bekommen habe ich gefühlt 132 mal ohne Ergebnis verworfen :)
 

akretschmer

Datenbank-Guru
Beiträge
9.848
Versuche das jetzt zu "Muss in 3 Monaten geprüft werden oder ist schon überfällig" zu bekommen habe ich gefühlt 132 mal ohne Ergebnis verworfe

Vergleiche das letzte Prüfdatum mit dem heutigen, ob es älter ist als 3 Monate. Deine Abfrage ist übrigens sysntaktisch falsch. MySQL erkennt dies nicht und liefert zufällige Ergebnisse, alle anderen Datenbanken würden einen Syntaxfehler liefern.
Warum? alle Spalten bei einer Aggregation (hier: max()) müssen entweder aggregiert oder gruppiert werden. Ist nicht der Fall.
 

akretschmer

Datenbank-Guru
Beiträge
9.848
das sind deine erfolgten Prüfungen, du willst alle nr haben, für die eine Prüfung älter als 3 monate ist:

Code:
edb=*# select * from pruefungen ;
 nr |       datum       
----+--------------------
  1 | 01-JAN-21 00:00:00
  2 | 01-APR-20 00:00:00
  3 | 01-FEB-20 00:00:00
  3 | 01-APR-21 00:00:00
(4 rows)

edb=*# select nr, max(datum) from pruefungen where datum < current_date - '3 month'::interval group by nr;
 nr |        max         
----+--------------------
  3 | 01-FEB-20 00:00:00
  2 | 01-APR-20 00:00:00
  1 | 01-JAN-21 00:00:00
(3 rows)

edb=*#
 

TheRealBllue

Neuer Benutzer
Beiträge
3
Die untere Variante habe ich einzeln sogar ähnlich hinbekommen. Aber wie bringe ich das im Anschluss wieder zusammen? Wenn ich da einfach JOIN feuerloescher ON... anhänge klappt es erwartungsgemäß nicht
 
Werbung:
Oben