MySQL: DELETE with sub-query on same table

I had an issue with a MySQL query containing a sub-query recently where it worked fine when done as a SELECT query, but gave an error when switching it to a DELETE query. The error given was something like ‘You can’t specify target table “items” for update in FROM clause’. The sub-query was referencing the same table as the main query, which apparently can’t be done directly in MySQL because the table will be modified during deletion. But there is a sort of a hack I found in this StackOverflow answer, among others, to force it to create a temp table and allow it to work.

The query selected items with some conditions including being the only item in a given list, that being where the sub-query came in. The original query looked something like this:

SELECT *, (
    SELECT COUNT(i2.id) FROM items i2 WHERE i2.list_id = il.id
) AS icnt
FROM items i
LEFT JOIN item_lists il ON il.id = i.list_id
WHERE i.condition = 'value'
AND (
    SELECT COUNT(i3.id) FROM items i3 WHERE i3.list_id = il.id
) = 1

Just changing the SElECT part to DELETE i gave the “target table” error. To make it work as a DELETE query, I had to modify the sub-query to have its own nested sub-query. This is what forces the temp table to be created. The inner sub-query cannot reference tables from the main query though, so I had to put that part in the outer sub-query. The end result looked something like this:

DELETE i
FROM items i
LEFT JOIN item_lists il ON il.id = i.list_id
WHERE i.condition = 'value'
AND (
    SELECT COUNT(i3.id) FROM (
        SELECT id, list_id FROM items i4
    ) AS i3 WHERE i3.list_id = il.id
) = 1

It did what I wanted. This would also have to be done for an UPDATE and presumably INSERT query. Hopefully I’ll be able to remember this the next time I encounter it.