MySQL Datensätze löschen aber die neusten behalten

Oft gibt es Tabellen wo nur eine bestimmte Anzahl von Datensätzen benötigt werden. Ein gutes Beispiel ist die Anzeige der letzten 10 besuchten Artikel eines Benutzers:

SELECT 
	`article_id`
FROM
	`history`
WHERE
	`user_id` = 1
ORDER BY
	`meta_created` DESC
LIMIT 10

Zum Löschen älterer Artikel würde jeder schnell zu folgender Query greifen:

DELETE FROM 
	`history`
WHERE
	`user_id` = 1
	AND `article_id` NOT IN(
		SELECT 
			`article_id`
		FROM
			`history`
		WHERE
			`user_id` = 1
		ORDER BY
			`meta_created` DESC
		LIMIT 10
	)

Jedoch gibt MySQL eine Fehlermeldung aus, dass die Benutzung von LIMIT in Subqueries nicht erlaubt ist. Auch die Verwendung von MIN oder MAX löst Fehler aus.

SQL Error (1235): MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

Eine andere Lösung wäre ROWNUM, wird aber nur in anderen Datenbanken wie Oracle nativ unterstützt, kann aber mit Hilfe von Variablen in MySQL simuliert werden.

DELETE FROM
	`history`
WHERE
	`user_id` = 1
	AND `article_id` IN (
		SELECT
			`H`.`ID`
		FROM (
			SELECT
				`article_id` AS `ID`,
				@rownum := @rownum + 1 AS `ROWNUM`
			FROM
				`history`,
				(SELECT @rownum:=0) `R`
			WHERE
				`user_id` = 1
			ORDER BY
				`meta_created` DESC
		) `H`
		WHERE
			`H`.`ROWNUM` > 10
	)

Da in meinem Beispiel die “article_id” nicht UNIQUE ist, also gleiche Artikel auch für andere Benutzer vorhanden sein können, muss “user_id” auch in der WHERE condition von DELETE vorhanden sein.

Kategorie: