Neuigkeiten:

Ist euer Problem gelöst, dann bitte den Knopf "Thema gelöst" drücken!

Mobiles Hauptmenü

in einem Jahr nicht anwesend

Begonnen von mad, September 17, 2019, 11:31:28

⏪ vorheriges - nächstes ⏩

mad

Hallo Zusammen,

bräuchte mal wieder eure Hilfe.
Mein Problem ist: Ich möchte alle Aktiven anzeigen lassen die keine Übung in einem der vergangen oder im aktuellen Jahr besucht haben.
Erfaßt werden die Übungsteilnehmer und deren Minuten über die Tabelle ,,Registrierung-Üb" und der Datum (ADatumU) über die Tabelle ,,Übungen". Zusätzlich befinden sich in der Abfrage noch diverse Tabellen um daraus noch Informationen zu generieren bzw. nach Ort zu filtern.
Ich lasse in der Abfrage die Summe der Minuten pro Aktiven und Jahr anzeigen.
Nun gibt es zwei Möglichkeiten warum ein Aktiver in einem Jahr keine Übung besucht hat:
1.   Er hat sich für eine oder mehrere Übungen Entschuldigt. Dann wird er für diese Übungen mit 0 Minuten registriert.
2.   Er war nie anwesend und auch nicht Entschuldigt, dann hat er für das entsprechende Jahr keine Eintragung.
Für den 1. Fall habe ich eine Lösung: Ich lasse nur die Datensätze anzeigen die in den ,,ÜbStdNMinAktiver" <1 also ,,0" ausweisen.

SELECT [Registrierung-Üb].Name, Year([ADatumU]) AS Jahre, Sum(DateDiff("n",0,[ÜbStdN])) AS ÜbStdNMinAktiver, Ortsteile.FW_Bezeichn, Ortsteile.Ort
FROM (Ortsteile INNER JOIN Personal ON Ortsteile.Ortkenn = Personal.Ortkenn) INNER JOIN (Übungen INNER JOIN [Registrierung-Üb] ON Übungen.UebKenn = [Registrierung-Üb].Übungen) ON Personal.Namekenn = [Registrierung-Üb].Name
WHERE (((Personal.statusID_P)=1 Or (Personal.statusID_P)=2))
GROUP BY [Registrierung-Üb].Name, Year([ADatumU]), Ortsteile.FW_Bezeichn, Ortsteile.Ort, Personal.Ortkenn
HAVING (((Year([ADatumU]))<=Year(Date())) AND ((Sum(DateDiff("n",0,[ÜbStdN])))<1) AND ((Personal.Ortkenn) Like [Bitte Ortskennung eingeben:]));


Für den 2. Fall fehlt mir eine Lösung.
Fall1 und Fall2 sollten möglichst auch über eine Abfrage angezeigt werden.
Wie könnte ich das lösen?

Über Hilfestellung würde ich mich sehr freuen.

Gruß
mad


PhilS

Zitat von: mad am September 17, 2019, 11:31:28
2.   Er war nie anwesend und auch nicht Entschuldigt, dann hat er für das entsprechende Jahr keine Eintragung.
Ich glaube du suchst einen LEFT OUTER JOIN im Gegensatz zu dem bisher verwendeten INNER JOIN.
Du musst dann nur die WHERE- bzw. HAVING-Klausel anpassen, so dass auch NULL-Werte ausgegeben werden.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

ebs17

ZitatÜber Hilfestellung würde ich mich sehr freuen.
Eine Abfrage würde ich aus Kenntnis des Beziehungsbildes und idealerweise aus zusätzlicher Kenntnis der Datenlage der Tabellen ableiten.

Prosa rundherum und das Analysieren von nicht ausreichend funktionierenden Wegen sind regelmäßig nicht hilfreich oder schlicht zu anstrengend.
Wenn man Ausgangspunkt und Ziel kennt, kann man selber Wege festlegen, die Durchaus ganz anders als nicht erfolgreiche Wege sein können.

Und grundsätzlich: Für etwas, was nicht existiert, würde ich ein NOT EXISTS-Konstrukt wählen (wie eben der Name so sagt ...).
Mit freundlichem Glück Auf!

Eberhard

mad

Hallo Zusammen,
vermutlich reichen meine Access-Kenntnisse dazu wieder mal nicht aus.

Gibt es im Netz eine gut erklärte Beschreibung (bitte kein Buch) zu dieser Thematik, eventuell mit einer kleinen Datenbank um das besser Verstehen zu können?
Dann würde ich mal versuchen mich darüber aufzuschlauen.

Probleme:
Welche Felder müssen miteinander Verklüpft werden fällt mir schwer zu verstehen.
Was ich auch nicht verstehe, den Unterschied zwischen HAVING und WHERE und die Anwendung. Wenn ich ein Kriterium eingebe gibt mir Access immer HAVING vor.
NOT EXISTS-Konstrukt?


Gruss
mad

MzKlMu

Hallo,
wie wäre es mal mit einem Bild des Beziehungsfensters ?

Damit man überhaupt mal eine Vorstellung hat über die Tabellenstruktur.
Gruß Klaus

mad


ebs17

ZitatMein Problem ist: Ich möchte alle Aktiven anzeigen lassen die keine Übung in einem der vergangen oder im aktuellen Jahr besucht haben.
Vermutlich kann man ausschließen, dass Übungen in zukünftigen Jahren besucht wurden.

Um dies inhaltlich abzuleiten, würde ich eine Personentabelle erwarten (Aktive?), wie dann auch eine Verbindung dieser mit Übungsterminen. Davon ist in Deiner Darstellung nichts Verwertbares erkennbar.
Eine Person, die noch keine Übung besucht hat, hätte also noch keinen Eintrag bei Übungsterminen. Zu lösen wäre das über eine Inkonsistenzprüfung: Menge aller relevanten Personen abzüglich der Menge der Personen mit Terminen.

ZitatWelche Felder müssen miteinander Verklüpft werden
Verknüpfungen ergeben sich meist aus bestehenden Beziehungen.

ZitatUnterschied zwischen HAVING und WHERE
WHERE heißt Filtern, und zwar vor einem Gruppieren.
HAVING heißt Filtern nach dem Gruppieren und ist nur sinnvoll auf gebildete Aggregate (Summen, Anzahlen, Maxima usw.).
Der Abfrageeditor arbeitet an der Stelle fehlerhaft.
Siehe auch Grundlagen - SQL ist leicht (11) - Reihenfolge der Abfrageabarbeitung
Mit freundlichem Glück Auf!

Eberhard

mad

#7
Hallo,
die Personal-Tab gibt es.
Ist halt immer schwierig in der heutigen Zeit mit Datenschutz.
Habe jetzt mal eine kleine Muster-DB mit angefügt, in der keine Echtnamen zu finden sind. Das Kriterium "1 oder 2" unter statusID_P filtert nach alle Aktiven.

Wenn man nun die Abfrage "qry_keine_Ueb_Aktiver_Jahr" ausführt kommen alle Aktiven die <1 Minuten (0 Minuten wegen entschuldigt) aufweisen.
Wenn man nun das Kriterium <1 entfernt und die Abfrage wieder ausführt werden alle Aktiven mit ihren jeweiligen Jahressummen in Minute gelistet.

Wenn man nun die Personenkennziffern sortiert und sich "füma" rauspickt, sieht man das er "0"-Werte hat aber auch zwei Jahre (siehe Bild1) in denen er nicht anwesend und nicht entschuldigt war.
Und genau diese Jahre sollten zu den mit "0" angezeigt werden.

Gruss
mad

ebs17

Tabellen mit Nachschlagefeldern darin fasse ich nicht an, weil es mir um die Zeit des Verstehens darin zu schade ist. Und erklären dazu wäre dann noch anstrengender.
Zu Nachschlagefeldern in Tabellen kannst Du selber recherchieren. Solche versteckten Verknüpfungen vermeidet der, der seine Abfragen verstehen will und somit alles mit einem Blick erfassen will.

Wer solchen Mist einsetzt, sollte das vollständig selber verstehen und auf Rückfragen bei anderen verzichten, einfach weil die da keine Anwendungspraxis haben und haben möchten.

Mit freundlichem Glück Auf!

Eberhard

MzKlMu

Hallo,
die Beziehung zwischen Personal und Registrierung-Üb ist auch falsch, Beziehungen laufen auf der 1-Seite immer über den Primärschlüssel (das ist ja auch der Sinn des PS) und auf der n-Seite über eine Zahl (Longinteger). Das entsprechende Feld fehlt in der Tabelle Registrierung-Üb.

Wirf unbdedingt die Nachschlagefelder raus.
Siehe hierzu:
http://dbwiki.net/wiki/Access_Anf%C3%A4nger:_Die_Nachteile_von_Nachschlagefeldern

Und außerdem:
Ein Feldname "Name" ist in einer Datenbank tabu, das ist eine Objekteigenschaft (auch in Englisch) und damit ein reserviertes Wort.


Gruß Klaus

mad

Hallo Zusammen,

danke erstmal für die Unterstützung. Das mit denn Auswahlfelder in der Tabelle waren Altlasten, habe ich jetzt umgestellt auf Textfelder.
Das mit den Beziehungen mag falsch sein, aber eine Umstellung ist mir ehrlich gesagt zuviel Risiko das meine DB anschliessend nicht mehr läuft. Bisher läuft sie seid 13 Jahren anstandslos.
Dafür muß ich halt jetzt auf eine perfekte Lösung verzichten. Hab es jetzt aber mit einer Kreuztabellenabfrage lösen können.
TRANSFORM Sum([Registrierung-Üb].ÜbStdN_min) AS SummevonÜbStdN_min
SELECT [Registrierung-Üb].Name
FROM Personal INNER JOIN (Übungen INNER JOIN [Registrierung-Üb] ON Übungen.UebKenn = [Registrierung-Üb].Übungen) ON Personal.Namekenn = [Registrierung-Üb].Name
WHERE (((Year([ADatumU])) Between Year(Date()) And Year(Date())-4) AND ((Personal.statusID_P)=1 Or (Personal.statusID_P)=2))
GROUP BY [Registrierung-Üb].Name, Personal.statusID_P
PIVOT Year([ADatumU]);


Das mit dem Feldnamen "Name" wird noch was grösseres!

Danke
mad