Uff, ohne Datenmodell ist erstmal Reengineering fällig :)
Also - deine Ausgabe besteht aus Kontaktadressen (wobei ich das merkwürdig finde, dass der Name an der Adresse steht und nicht am Kontakt, aber na gut, das mag Gründe haben...). Deine primäre Query ist also
SELECT k.KontaktNummer, an.Name, an.Strasse, an.Postleitzahl, an.Ort
FROM Kontakte k INNER JOIN Anschriften an
ON an.AnschriftsNummer = k.HauptAnschrift
und das sollte auch oben stehen. Die Kontaktnummer sollte aus der Kontakte-Tabelle gelesen werden, weil sie da der Primärschlüssel sein dürfte. Der Lesbarkeit halber.
Diese Abfrage wird nun eingegrenzt. Erstmal auf gültige Verträge, aber diese bitte als direkte Relation und nicht als Umweg über die Aktivitäten. Wieder aus Lesbarkeitsgründen.
SELECT k.KontaktNummer, an.Name, an.Strasse, an.Postleitzahl, an.Ort
FROM Kontakte k
INNER JOIN Anschriften an ON an.AnschriftsNummer = k.HauptAnschrift
INNER JOIN Vertragskoepfe vk ON vk.Kundennummer = k.KontaktNummer
WHERE vk.Vertragsende > GETDATE()
So. Und dass muss nun eingegrenzt werden auf die Fälle, wo es ausschließlich Aktivitäten gibt wo der AktivitätenMitarbeiter (eine m:n-Relation, ja?) den Bearbeitungsstatus 9 hat. Das macht man mit einer EXISTS Abfrage. Wir wollen nur die haben, die 9 sind - was sich durch doppelte Verneinung abfragen lässt: es darf keinen geben, der nicht 9 ist.
SELECT k.KontaktNummer, an.Name, an.Strasse, an.Postleitzahl, an.Ort
FROM Kontakte k
INNER JOIN Anschriften an ON an.AnschriftsNummer = k.HauptAnschrift
INNER JOIN Vertragskoepfe vk ON vk.Kundennummer = k.KontaktNummer
WHERE vk.Vertragsende > GETDATE()
AND NOT EXISTS (SELECT *
FROM Aktivitaeten ak JOIN AktivitaetenMitarbeiter am ON ak.LfdNr = am.LfdNr
WHERE ak.KontaktNummer = k.KontaktNummer
AND am.Bearbeitungsstatus <> 9)
Das sollte so bis auf Flüchtigkeitsfehler (weil nicht getestet) stimmen.
Wozu Du den GROUP BY brauchst, weiß ich nicht, du hattest keine Aggregation in der SELECT Liste. Ich habe ihm darum weggelassen.
Rolf