SQL Statement - Help

mitch_byu_kennen

Erfahrenes Mitglied
Hallo,

ich benötige hilfe bei einem SQL- Statement.

Ich habe folgende Tabelle mit dem Namen
AP (AP_ID, Name, Vorname, AP_FREMD_ID, USER_ID),
APVG (AP_ID,VG_ID),
ADR (ADR_ID, AP_ID, STRASSE, ORT)

In der Tabelle AP habe ich folgende Einträge:
AP_ID = 1, Meier, Max, F10, 99
AP_ID = 2, Meier, Max, F10, 99
AP_ID = 3, Meier, Max, F10, 99
AP_ID = 4, Meier, Max, F10, 99

In der Kreuztabelle APVG steht folgendes:
AP_ID= 1, VG_ID= 10
AP_ID= 2, VG_ID= 19
AP_ID= 3, VG_ID= 106
AP_ID= 3, VG_ID= 15

In der ADR Tabelle steht:
ADR_ID=1, AP_ID=1, Musterstraße, Musterort
ADR_ID=2, AP_ID=2, Musterstraße, Musterort
ADR_ID=5, AP_ID=3, Musterstraße, Musterort
ADR_ID=9, AP_ID=4, Musterstraße, Musterort


Ich will jetzt, dass in der AP Tabelle es nur noch eine Kombination aus USER_ID und FREMD_ID gibt. Die überflüssigen dopplungen sollten gelöscht werden. Zusätzlich müssen in der Kreuztabelle APVG alle Datensätze auf den einen übriggebliebenen AP verweisen (da die dopplungen ja gelöscht werden sollen). Die Tabelle ADR soll ebenfalls bereinigt werden.


Ist das überhaupt mit SQL möglich?

gruß
 
So kompliziert ist es nicht.

Dazu verwenden wir MySQL Aktuelle Einträge pro Gruppe auslesen (mit INNER JOIN) und drehen den Spiess einfach um. Wir wählen den Datensatz mit der kleinsten ID. Diese sind die Einträge die am Schluss übrig bleiben
SQL:
-- [not_delete]
SELECT
	MIN(ap_id) AS ap_id,
	ap_sel.ap_fremd_id,
	user_id
FROM
	ap AS ap_sel
GROUP BY
	ap_sel.ap_fremd_id,
	ap_sel.user_id

Darauf bauen wir nun auf.

Lesen wir mal aus, welche ap_id auf welche neue ap_id gesetzt werden muss. Das brauchen wir für Bereinigung der APVG
SQL:
-- [new_ids]
SELECT 
	ap.ap_id,
	not_delete.ap_id AS new_id
FROM
	ap 
	LEFT JOIN  ( [not_delete]) AS not_delete
		ON  not_delete.ap_fremd_id = ap.ap_fremd_id 
		AND not_delete.user_id = ap.user_id

Und wenn wir jetzt [not_delete] durch den Code ersetzen, bekommen wir das folgende

SQL:
-- new_ids
SELECT 
	ap.ap_id,
	not_delete.ap_id AS new_id
FROM
	ap 
	LEFT JOIN  (
			SELECT
				MIN(ap_id) AS ap_id,
				ap_sel.ap_fremd_id,
				user_id
			FROM
				ap AS ap_sel
			GROUP BY
				ap_sel.ap_fremd_id,
				ap_sel.user_id
		) AS not_delete
		ON  not_delete.ap_fremd_id = ap.ap_fremd_id 
		AND not_delete.user_id = ap.user_id

Das war mal kurz ein Wenig Grundlagen. Also noch nicht sehr komplex.

Zuerst muss die Zuordnungstabelle bereinigt werden, denn noch wissen wir welche ap_id auf welche neuen ids kommen.

APVG
Einfach noch die apvg-Tabele hinzufügen und ein UPDATE daraus basteln und schon haben wir alle Einträge in der apvg-Tabelle auf die zukünftig gültigen ap_ids umgeschrieben
SQL:
UPDATE
	ap 
	INNER JOIN apvg
		ON apvg.ap_id = ap.ap_id
	LEFT JOIN  (
			SELECT
				MIN(ap_id) AS ap_id,
				ap_sel.ap_fremd_id,
				user_id
			FROM
				ap AS ap_sel
			GROUP BY
				ap_sel.ap_fremd_id,
				ap_sel.user_id
		) AS not_delete
		ON  not_delete.ap_fremd_id = ap.ap_fremd_id 
		AND not_delete.user_id = ap.user_id
-- die ap_id im apvg mit derjenigen der not_delete-Menge überschreiben
SET apvg.ap_id = not_delete.ap_id

AP
Nun noch die überflüssigen Einträge der ap entfernen. Sieht wieder fast gleich aus.
Wieder unsere Auswahl verknüpfen (dieses mal inkl. ID) und auf NULL prüfen.
SQL:
DELETE
	ap.*
FROM
	ap 
	LEFT JOIN  (
			SELECT
				MIN(ap_id) AS ap_id,
				ap_sel.ap_fremd_id,
				user_id
			FROM
				ap AS ap_sel
			GROUP BY
				ap_sel.ap_fremd_id,
				ap_sel.user_id
		) AS not_delete
		-- Hier nun auch auf die ID vergleichen
		ON not_delete.ap_id = ap.ap_id
		AND not_delete.ap_fremd_id = ap.ap_fremd_id 
		AND not_delete.user_id = ap.user_id
WHERE
	not_delete.ap_id IS NULL;

So einfach geht das mit SQL.

Und für die ADR geht genauso. Einfach die SQL-Statements ein wenig anpassen
 
Zuletzt bearbeitet von einem Moderator:
Hallo und danke für deine Antwort, die Lösung kann ich nachvollziehen.

Bei mir entsteht momentan noch ein Problem, der SQLDeveloper meckert "missing Set keyword".
Hängt das damit zusammen, dass es sich um eine Oracle Datenbank handelt? Mein Statement sieht so aus: (anstelle der USER_ID habe ich eine andere ID genommen - vorerrst)
SQL:
UPDATE ap INNER JOIN apvg ON apvg.ap_id = ap.ap_id 
LEFT JOIN (SELECT MIN(ap_id) AS ap_id, ap.ap_fremd_id, ap.ap_adr_id
           FROM ap group by ap.ap_fremd_id, ap.ap_adr_id) AS not_delete
ON  not_delete.ap_fremd_id = ap.ap_fremd_id 
AND not_delete.ap_adr_id = ap.ap_adr_id 
SET apvg.ap_id = not_delete.ap_id
 
Oh, mein Beispiel war für MySQL. Bei Oracle kommt das SET vor den Join und das ganze müsste dann etwa so aussehen um apvg anzupassen
SQL:
UPDATE
	apvg
SET
	apvg.ap_id = 
	(
		SELECT
			not_delete.ap_id
		FROM
			ap 
			LEFT JOIN  (
					SELECT
						MIN(ap_id) AS ap_id,
						ap_sel.ap_fremd_id,
						user_id
					FROM
						ap AS ap_sel
					GROUP BY
						ap_sel.ap_fremd_id,
						ap_sel.user_id
				) AS not_delete
				ON  not_delete.ap_fremd_id = ap.ap_fremd_id 
				AND not_delete.user_id = ap.user_id	
		WHERE
			ap.ap_id = apvg.ap_id
	);
 
Zuletzt bearbeitet von einem Moderator:
Ja so funktioniert es schon mal, nun wird es noch etwas komplexer. :)

Es ist ja so, dass bisher die AP_FREMDID in Gruppen zusammengefasst wurden, welche die selbe USER_ID haben. Nun, diese USER_ID habe ich nicht in der AP Tabelle.
Zu der APVG Tabelle gibt es eine VG Tabelle. Diese VG Tabelle wiederum ist verbunden mit einer KU Tabelle. Ein Eintrag in der KU Tabelle kann mehrere Einträge in der VG Tabelle haben.
In der KU Tabelle gibt es die benötigte USER_ID.

Die KU Tabelle ist wiederum verknüpft mit der USER Tabelle. Ein USER kann mehrere Einträge in der KU Tabelle haben.

Und ich muss jetzt sicher stellen, dass nur die AP_FREMDIDs mit der selben USER_ID zusammengefasst werden.

Ich hoffe Ihr konnte mir noch folgen. :/
 
Jetzt wird es spannend

Bisher hatten wir ja das folgende als Grundkonstrukt um die neuen IDs zu ermitteln
SQL:
SELECT
   MIN(ap.ap_id) AS ap_id,
   ap.ap_fremd_id,
   ap.user_id
FROM
   ap
GROUP BY
   ap.ap_fremd_id,
   ap.user_id

Hier müssen wir jetzt einfach die user_id aus der KU herleiten
SQL:
SELECT
   MIN(ap.ap_id) AS ap_id,
   ap.ap_fremd_id,
   ku.user_id
FROM
   ap
   LEFT JOIN apvg
   	ON ap.ap_id = apvg.ap_id
   LEFT JOIN vg
   	ON apvg.vg_id = vg.vg_id
   LEFT JOIN ku
   	ON vg.ku_id = ku.ku_id
GROUP BY
   ap.ap_fremd_id,
   ku.user_id

Diesen Kern einfach in allen SQLs ersetzen und schon hast du es.
 
Zuletzt bearbeitet von einem Moderator:

Neue Beiträge

Zurück