Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit
Kommentar vom Moderator Biber am 22.06.2012 um 16:02:05 Uhr
Verschoben von PHP nach Datenbanken.
GELÖST

MySQL Doppelte elemente löschen! Ältestes element beibehalten!

Frage Entwicklung Datenbanken

Mitglied: Roadrunner777

Roadrunner777 (Level 1) - Jetzt verbinden

20.06.2012, aktualisiert 22.06.2012, 7313 Aufrufe, 24 Kommentare

Hallo,

ich habe Grundlegende PHP und MySQL fähigkeiten aber dafür reichts dann leider doch nicht!

ich habe eine Tabelle und die schaut ca. so aus!



ID |. Auftrags_NR | Unterauftrag | Status | LASTCHANGE
1 .|. 123 ..............| 1 ...............| 100 .....| 2012-06-19 07:49:12
2 .|. 123 ..............| 1 ...............| 100 .....| 2012-06-19 07:51:10
3 .|. 123 ..............| 1 ...............| 100 .....| 2012-06-19 07:52:05
4 .|. 125 ..............| 1 ...............| 100 .....| 2012-06-19 08:01:55
5 .|. 125 ..............| 1 ...............| 200 .....| 2012-06-19 08:02:12


ID -> INDEX,... immer anders in diesen Fall uninsteressant!

Die Schlüsselwerte für das Suchen und Löschen sind Auftrags_Nr, Unterauftrag und Status! LASTCHANGE ist das Datum andem der Datensatz das letzte mal geändert wurde (klingt komisch, ist aber so).

Ich suche eine Funktion die feststellt das (wie im Beispiel) ID 1, 2 und 3 gleich sind und dann alle doppelten Werte löscht (außer dem ältesten -> ID 1).

mein ansatz:
$delete_twice = "DELETE FROM tabelle WHERE ... ORDER BY LASTCHANGE ASC LIMIT 1, 99";
Aber irgendwie find ich keine richtige bedingung!

Vielen Dank für euere Unterstützung

Beste Grüße
RoadRunner
Mitglied: nxclass
20.06.2012, aktualisiert um 08:52 Uhr
außer dem ältesten
.. sagen wir mal: "dem ersten" ?

Du brauchst eine Liste mit allen "ersten" IDs.
01.
SELECT * FROM Tabelle 
02.
GROUP BY Auftrags_NR
..sollte schon reichen, da MySQL wohl immer die nicht im GROUP oder in einer Aggregat Funktion gepackten Felder, den ersten gefundenen Datensatz zurück gibt.

Nun machst mit dieser Ergebnismenge ein LEFT JOIN über die Tabelle und prüfst auf NULL
01.
SELECT ID FROM Table t1 LEFT JOIN ( 
02.
  SELECT * FROM Tabelle 
03.
  GROUP BY Auftrags_NR 
04.
) t2 ON (t1.ID = t2.ID) 
05.
WHERE t2 IS NULL
nun hast du die Liste der zu löschenden Datensätze
01.
DELETE FROM Table WHERE ID IN ( 
02.
  SELECT ID FROM Table t1 LEFT JOIN ( 
03.
    SELECT * FROM Tabelle 
04.
    GROUP BY Auftrags_NR 
05.
  ) t2 ON (t1.ID = t2.ID) 
06.
  WHERE t2 IS NULL 
07.
)
..ungetestet - so ich arbeite mal weiter...

EDIT: gehört eigentlich zu MySQL / Datenbanken - dieses Problem
Bitte warten ..
Mitglied: godlie
20.06.2012 um 08:56 Uhr
Also,
ein Group BY ohne ORDER wäre in diesem Fall sehr fatal.
Bitte warten ..
Mitglied: Roadrunner777
20.06.2012 um 09:40 Uhr
Danke erstmal!

>.. sagen wir mal: "dem ersten" ?

naja, ich meinte aber schon den ältesten (nach LASTCHANGE) - da es theoretisch möglich ist das einer der ersten bearbeitet wird und dann eine höhere ID, einen älteren Wert hat -> Klinkt komisch ist aber so!

Des weiteren kann es sein, das ich zwar die selbe Auftrags_NR habe, aber einen anderen unterauftrag! diese sollten dann nicht gelöscht werden! ebenso mit der Status ID

letztendlich möchte ich immer den maximalältesten (LASTCHANGE) Wert von jeder Auftrags_NR, Unterauftrag und Status Kombination haben!

Vielen Dank
Bitte warten ..
Mitglied: Roadrunner777
20.06.2012 um 09:42 Uhr
Zitat von godlie:
Also,
ein Group BY ohne ORDER wäre in diesem Fall sehr fatal.

Das heißt?
-> Welche auswirkungen hat ein ODER auf Group By? Und wie mach ichs richtig?
Bitte warten ..
Mitglied: godlie
20.06.2012 um 09:46 Uhr
Ein GROUP BY <-- wie der name sagt Gruppiert etwas nach einem Kriterium
Ein ORDER BY <-- sortiert etwas nach einem gewissem Kriterium
Bitte warten ..
Mitglied: Roadrunner777
20.06.2012 um 09:55 Uhr
ja OK,... aber warum sollte es fatal sein, wenn ich nicht sortiere wärend ich gruppiere?

und, ja leider bekomm ichs nicht hin!

wie genau muss ich die Abfrage aufbauen?
Bitte warten ..
Mitglied: LianenSchwinger
20.06.2012, aktualisiert um 11:31 Uhr
Hallo,

ich denke es sollte wie folgt funktionieren:

01.
DELETE FROM tabelle c 
02.
WHERE c.ID NOT IN (SELECT a.ID  
03.
                   FROM tabelle a 
04.
                   INNER JOIN (SELECT t.AUFTRAGS_NR, t.UNTERAUFTRAG, t.STATUS, MIN(t.LASTCHANGE) AS LC 
05.
                               FROM tabelle t 
06.
                               GROUP BY t.AUFTRAGS_NR, t.UNTERAUFTRAG, t.STATUS) b  
07.
                   ON a.AUFTRAGS_NR = b.AUFTRAGS_NR 
08.
                   AND a.UNTERAUFTRAG = b.UNTERAUFTRAG 
09.
                   AND a.STATUS = b.STATUS 
10.
                   AND a.LASTCHANGE = b.LC)
Gruß Jörg
Bitte warten ..
Mitglied: LianenSchwinger
20.06.2012 um 10:14 Uhr
Zitat von Roadrunner777:
ja OK,... aber warum sollte es fatal sein, wenn ich nicht sortiere wärend ich gruppiere?

und, ja leider bekomm ichs nicht hin!

wie genau muss ich die Abfrage aufbauen?

... man Sortiert nicht während des Gruppierens.
Sondern es werden die Datensätze nach dem Gruppieren sortiert.

Von daher glaube ich nicht, dass die Aussage aus dem 1. Post

..sollte schon reichen, da MySQL wohl immer die nicht im GROUP oder in einer Aggregat Funktion gepackten Felder, den > ersten gefundenen Datensatz zurück gibt.

funktioniert.

Gruß Jörg
Bitte warten ..
Mitglied: nxclass
20.06.2012, aktualisiert um 12:00 Uhr
ein Group BY ohne ORDER wäre in diesem Fall sehr fatal.
... man Sortiert nicht während des Gruppierens.
Sondern es werden die Datensätze nach dem Gruppieren sortiert.
... ein GROUP löst autom. auch ein ORDER über die angegebenen Felder aus.
Man müsste sogar:
01.
GROUP BY Feld 
02.
ORDER BY NULL
schreiben um ein Sortieren zu verhindern (für bessere Performance ggf sinnvoll)
ABER: das ORDER nach dem GROUP ist eh nicht wichtig - wenn dann müsste das ORDER vor dem Gruppieren gemacht werden.

Das Beispiel sollte funktionieren, WENN: die Daten in LASTCHANGE auch der Reihenfolge beim Speichern in der DB entsprechen. Ansonsten muss man vorher noch ein SUB SELECT mit ORDER ausführen.

EDIT: in Post 1 ist ein Fehler:
01.
/* SELECT * FROM Table WHERE ID IN ( */ 
02.
DELETE FROM Table WHERE ID IN ( 
03.
  SELECT t1.ID FROM Table t1 LEFT JOIN ( 
04.
    SELECT * FROM Tabelle 
05.
    GROUP BY Auftrags_NR 
06.
  ) t2 ON (t1.ID = t2.ID) 
07.
  WHERE t2.ID IS NULL 
08.
)
mit Verbesserung:
01.
/* SELECT * FROM Table WHERE ID IN ( */ 
02.
DELETE FROM Table WHERE ID IN ( 
03.
  SELECT t1.ID FROM Table t1 LEFT JOIN ( 
04.
    SELECT tmp.* FROM ( SELECT * FROM Table ORDER BY LASTCHANGE ) tmp 
05.
    GROUP BY tmp.Auftrags_NR 
06.
  ) t2 ON (t1.ID = t2.ID) 
07.
  WHERE t2.ID IS NULL 
08.
)
Bitte warten ..
Mitglied: Roadrunner777
20.06.2012 um 11:42 Uhr
Zitat von LianenSchwinger:
Hallo,

ich denke es sollte wie folgt funktionieren:

01.
> DELETE FROM tabelle 
02.
> WHERE ID NOT IN (SELECT ID  
03.
>                  FROM tabelle a 
04.
>                  INNER JOIN (SELECT AUFTRAGS_NR, UNTERAUFTRAG, STATUS, MIN(LASTCHANGE) LC 
05.
>                              FROM tabelle 
06.
>                              GROUP BY AUFTRAGS_NR, UNTERAUFTRAG, STATUS) b  
07.
>                     ON a.AUFTRAGS_NR = b.AUFTRAGS_NR 
08.
>                     AND a.UNTERAUFTRAG = b.UNTERAUFTRAG 
09.
>                     AND a.STATUS = b.STATUS 
10.
>                     AND a.LASTCHANGE = b.LC) 
11.
> 
Gruß Jörg

leider gibt er mir nur:

01.
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM cd_status WHERE ID NOT IN (SELECT ID FROM cd_status a ' at line 1
Zurück.

Woran kann es liegen?
Bitte warten ..
Mitglied: nxclass
20.06.2012 um 11:47 Uhr
Da fehlt die Orginal SQL Anweisung. Wenn du aus dem DELETE ein SELECT gemacht hast, ist evtl nur ein , zuviel !?
Bitte warten ..
Mitglied: LianenSchwinger
20.06.2012, aktualisiert um 11:59 Uhr
... poste bitte mal Deine komplette Anweisung.

Könnte sein, das Du vor dem FROM ein "," stehen hast.
Bitte warten ..
Mitglied: Roadrunner777
20.06.2012 um 14:59 Uhr
01.
 
02.
                               $delete_twice = " 
03.
SELECT FROM cd_status 
04.
WHERE ID NOT IN (SELECT ID  
05.
                 FROM cd_status a 
06.
                 INNER JOIN (SELECT Auftrags_NR, Unterauftrag, Status, MIN(LASTCHANGE) LC 
07.
                             FROM cd_status 
08.
                             GROUP BY Auftrags_NR, Unterauftrag, Status) b  
09.
                    ON a.Auftrags_NR = b.Auftrags_NR 
10.
                    AND a.Unterauftrag = b.Unterauftrag 
11.
                    AND a.Status = b.Status 
12.
                    AND a.LASTCHANGE = b.LC) 
13.
                               "; 
14.
                                
15.
                               $delete = mysql_query($delete_twice) or die(mysql_error());
aber auch

01.
                               $delete_twice = " 
02.
SELECT * FROM Table WHERE ID IN (  
03.
  SELECT t1.ID FROM Table t1 LEFT JOIN ( 
04.
    SELECT tmp.* FROM ( SELECT * FROM Table ORDER BY LASTCHANGE ) tmp 
05.
    GROUP BY tmp.Auftrags_NR 
06.
  ) t2 ON (t1.ID = t2.ID) 
07.
  WHERE t2.ID IS NULL 
08.
09.
                               "; 
10.
                                
11.
                               $delete = mysql_query($delete_twice) or die(mysql_error()); 
12.
 
13.
 
gibt mir folgenden Fehler zurück

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Table WHERE ID IN ( SELECT t1.ID FROM Table t1 LEFT JOIN ( SELECT tmp.*' at line 1
Bitte warten ..
Mitglied: LianenSchwinger
20.06.2012, aktualisiert um 15:26 Uhr
... bei der oberen fehlt der "*" nach dem SELECT und bei der unteren hast Du das reservierte Wort "Table" verwendet.

01.
SELECT c.* FROM cd_status c 
02.
WHERE c.ID NOT IN (SELECT a.ID  
03.
                   FROM cd_status a 
04.
                   INNER JOIN (SELECT t.AUFTRAGS_NR, t.UNTERAUFTRAG, t.STATUS, MIN(t.LASTCHANGE) AS LC 
05.
                               FROM cd_status t 
06.
                               GROUP BY t.AUFTRAGS_NR, t.UNTERAUFTRAG, t.STATUS) b  
07.
                   ON a.AUFTRAGS_NR = b.AUFTRAGS_NR 
08.
                   AND a.UNTERAUFTRAG = b.UNTERAUFTRAG 
09.
                   AND a.STATUS = b.STATUS 
10.
                   AND a.LASTCHANGE = b.LC)
Habe gerade auf meiner Oracle-Datenbank genau die Anweisung ohne Fehlermeldung abgesetzt.

01.
SELECT c.* FROM ifsapp.inventory_transaction_hist c 
02.
WHERE c.transaction_id NOT IN (SELECT a.transaction_id 
03.
                               FROM ifsapp.inventory_transaction_hist a 
04.
                               INNER JOIN (SELECT t.order_no, t.release_no, t.line_item_no,  
05.
                                                  MIN(t.date_created) AS LC 
06.
                                           FROM ifsapp.inventory_transaction_hist t 
07.
                                           GROUP BY t.order_no, t.release_no, t.line_item_no) b  
08.
                               ON a.order_no = b.order_no 
09.
                               AND a.release_no = b.release_no 
10.
                               AND a.line_item_no = b.line_item_no 
11.
                               AND a.date_created = b.LC)
Gruß Jörg
Bitte warten ..
Mitglied: Roadrunner777
20.06.2012 um 15:36 Uhr
Jaaaaaaa,... es geht!

ich werds mal nochmal genau testen (da es immerhin einige tausend datensätze sind die ich dann lösche) aber es schaut gut aus!


Zitat von LianenSchwinger:
... bei der oberen fehlt der "*" nach dem SELECT und bei der unteren hast Du das reservierte Wort "Table"
verwendet.

-> hm,.... ja ich bin eh dafür das blödheit bestraft wird ^^

sorry mein fehler!

Danke erstmal für eure Hilfe!
Bitte warten ..
Mitglied: LianenSchwinger
20.06.2012, aktualisiert um 15:44 Uhr
... welche Version funktioniert denn jetzt, wenn beide, geben sie die selben Daten aus?

Und nicht vergessen die Frage als "gelöst" markieren.

Gruß Jörg
Bitte warten ..
Mitglied: Roadrunner777
21.06.2012 um 09:42 Uhr
Zitat von LianenSchwinger:
... welche Version funktioniert denn jetzt, wenn beide, geben sie die selben Daten aus?

ich verwende jetzt die da!

01.
		$delete_twice = " 
02.
		SELECT c.* FROM cd_status c 
03.
		WHERE c.ID NOT IN (SELECT a.ID  
04.
		FROM cd_status a 
05.
		INNER JOIN (SELECT t.Auftrags_NR, t.Unterauftrag, t.Status, MIN(t.LASTCHANGE) AS LC 
06.
		FROM cd_status t 
07.
		GROUP BY t.Auftrags_NR, t.Unterauftrag, t.Status) b  
08.
		ON a.Auftrags_NR = b.Auftrags_NR 
09.
		AND a.Unterauftrag = b.Unterauftrag 
10.
		AND a.Status = b.Status 
11.
		AND a.LASTCHANGE = b.LC)";
und die gibt auch das richtige aus!

allerdings hab ich noch n problem,... denn wenn ich das jetzt so abändere (SELECT wird durch DELETE ausgetauscht)

01.
		$delete_twice = " 
02.
		DELETE c.* FROM cd_status c 
03.
		WHERE c.ID NOT IN (SELECT a.ID  
04.
		FROM cd_status a 
05.
		INNER JOIN (SELECT t.Auftrags_NR, t.Unterauftrag, t.Status, MIN(t.LASTCHANGE) AS LC 
06.
		FROM cd_status t 
07.
		GROUP BY t.Auftrags_NR, t.Unterauftrag, t.Status) b  
08.
		ON a.Auftrags_NR = b.Auftrags_NR 
09.
		AND a.Unterauftrag = b.Unterauftrag 
10.
		AND a.Status = b.Status 
11.
		AND a.LASTCHANGE = b.LC)";
gibt er mir
01.
You can't specify target table 'c' for update in FROM clause
zurück
Bitte warten ..
Mitglied: LianenSchwinger
21.06.2012 um 09:52 Uhr
... lass mal das c.* nach dem DELETE weg.

Gruß Jörg
Bitte warten ..
Mitglied: Roadrunner777
21.06.2012 um 10:24 Uhr
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'c WHERE c.ID NOT IN (SELECT a.ID FROM cd_status a INNER JOIN (SELECT t' at line 1

Beste Grüße
RoadRunner
Bitte warten ..
Mitglied: LianenSchwinger
21.06.2012, aktualisiert um 10:36 Uhr
Hallo RoadRunner,

MySQL scheint keinen Alias für die Tabelle aus der gelöscht werden soll zu mögen, versuch mal:

01.
DELET FROM cd_status 
02.
WHERE ID NOT IN (...)
Gruß Jörg
Bitte warten ..
Mitglied: Roadrunner777
21.06.2012 um 10:39 Uhr
01.
		$delete_twice = " 
02.
		DELETE FROM cd_status 
03.
		WHERE ID NOT IN (SELECT a.ID  
04.
		FROM cd_status a 
05.
		INNER JOIN (SELECT t.Auftrags_NR, t.Unterauftrag, t.Status, MIN(t.LASTCHANGE) AS LC 
06.
		FROM cd_status t 
07.
		GROUP BY t.Auftrags_NR, t.Unterauftrag, t.Status) b  
08.
		ON a.Auftrags_NR = b.Auftrags_NR 
09.
		AND a.Unterauftrag = b.Unterauftrag 
10.
		AND a.Status = b.Status 
11.
		AND a.LASTCHANGE = b.LC)";
01.
You can't specify target table 'cd_status' for update in FROM clause
tut mir leid!... hab ich ne falsche MySQL version? oder warum bekomm ichs net hin?
Bitte warten ..
Mitglied: LianenSchwinger
21.06.2012, aktualisiert um 11:31 Uhr
OK, er scheint kein Subselect mit der Tabelle zu mögen, aus der Zeilen gelöscht werden sollen.
Das heißt, Du musst Dir die zu löschenden ID mittels

01.
CREATE TABLE tmp_cd_status_id  
02.
SELECT c.ID from cd_status c 
03.
WHERE c.ID NOT IN (...)
in eine temporäre Tabelle speichern und dann ...

01.
DELETE FROM cd_status 
02.
WHERE ID IN (SELECT ID FROM tmp_tabelle)
Am Ende noch weg mit der Temp-Tabelle

01.
DROP TABLE tmp_cd_status_id
Gruß Jörg
Bitte warten ..
Mitglied: Roadrunner777
21.06.2012 um 12:24 Uhr
Sehr schön!

Vielen Dank!
Bitte warten ..
Mitglied: nxclass
21.06.2012, aktualisiert um 21:12 Uhr
You can't specify target table 'cd_status' for update in FROM clause
hab ich ne falsche MySQL version?
er scheint kein Subselect mit der Tabelle zu mögen,
... es handelt sich wohl um MyISAM Tabellen - diese sind zwar schnell beim ändern von Daten, müssen dazu aber die betreffende Tabelle sperren. Ein SELECT während des UPDATEs / DELETEs ist somit nicht möglich.

EDIT:
Sollte es sich um sehr viele zu löschende Daten handeln, könnte man die zu erhaltenen Daten auch in die temp. Tabelle übertragen. Danach ein TRUNCATE ausführen (TRANCATE ist sehr viel schneller) und anschließend die Daten wieder einspielen.
Bitte warten ..
Neuester Wissensbeitrag
Internet

Unbemerkt - Telekom Netzumschaltung! - BNG - Broadband Network Gateway

(3)

Erfahrungsbericht von ashnod zum Thema Internet ...

Ähnliche Inhalte
Exchange Server
gelöst SBS2011 - im Exchange mobile Geräte löschen (4)

Frage von MiSt zum Thema Exchange Server ...

Exchange Server
Inhalt von Postfächern in Exchange löschen (9)

Frage von m.reeger zum Thema Exchange Server ...

Heiß diskutierte Inhalte
Switche und Hubs
Trunk für 2xCisco Switch. Wo liegt der Fehler? (15)

Frage von JayyyH zum Thema Switche und Hubs ...

DSL, VDSL
DSL-Signal bewerten (13)

Frage von SarekHL zum Thema DSL, VDSL ...