27

I need to query a delete statement for the same table based on column conditions from the same table for a correlated subquery.

I can't directly run a delete statement and check a condition for the same table in mysql for a correlated subquery.

I want to know whether using temp table will affect mysql's memory/performance?

Any help will be highly appreciated.

Thanks.

Sharpeye500
  • 8,775
  • 25
  • 95
  • 143

7 Answers7

47

You can make mysql do the temp table for you by wrapping your "where" query as an inline from table.

This original query will give you the dreaded "You can't specify target table for update in FROM clause":

DELETE FROM sametable
WHERE id IN (
    SELECT id FROM sametable WHERE stuff=true
)

Rewriting it to use inline temp becomes...

DELETE FROM sametable
WHERE id IN (
 SELECT implicitTemp.id from (SELECT id FROM sametable WHERE stuff=true) implicitTemp
)
Adam Lane
  • 1,784
  • 19
  • 25
  • 1
    I found this resulted in a very slow query. I'm not sure how slow because I gave up after 1-3 minutes. Using a JOIN as Bill Karwin's suggested was about 100ms. – phylae Nov 12 '16 at 01:31
  • 1
    This query is especially useful when we want to delete based on aggregate functions like MAX. Ex: deleting all entries in the table where the count variable is less than MAX(count) – Sunil Dabburi Apr 24 '18 at 17:02
25

Your question is really not clear, but I would guess you have a correlated subquery and you're having trouble doing a SELECT from the same table that is locked by the DELETE. For instance to delete all but the most recent revision of a document:

DELETE FROM document_revisions d1 WHERE edit_date < 
  (SELECT MAX(edit_date) FROM document_revisions d2 
   WHERE d2.document_id = d1.document_id);

This is a problem for MySQL.

Many examples of these types of problems can be solved using MySQL multi-table delete syntax:

DELETE d1 FROM document_revisions d1 JOIN document_revisions d2 
  ON d1.document_id = d2.document_id AND d1.edit_date < d2.edit_date;

But these solutions are best designed on a case-by-case basis, so if you edit your question and be more specific about the problem you're trying to solve, perhaps we can help you.

In other cases you may be right, using a temp table is the simplest solution.

Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
  • Thanks bill,Yes you got it right, am having trouble in executing correlated subquery delete in mysql. If i use the multi-table delete syntax, i straight away get this query in slow query log. (assume that you have 50K records in the table you are deleting, if i make a condition check using multi-delete syntax i immediately get this query in slow query log). So i went to temp table concept, my question is will temp table affect mysql's memory/performance? – Sharpeye500 Jul 27 '10 at 17:33
  • Of course a temp table takes some amount of resources, but keep in mind that MySQL creates temp tables on the fly for queries all the time. And the temp table is freed when the current mysql connection closes, so they're pretty short-lived. – Bill Karwin Jul 27 '10 at 17:56
  • However, I'd suggest investigating why your multi-table delete was so slow. It's fairly straightforward to write an equivalent SELECT that does the same join, and then you can use EXPLAIN to analyze the optimization plan for the SELECT (MySQL's EXPLAIN doesn't support DELETE). You might be able to create the right covering index to make the DELETE run fast. – Bill Karwin Jul 27 '10 at 18:12
2

can't directly run a delete statement and check a condition for the same table

Sure you can. If you want to delete from table1 while checking the condition that col1 = 'somevalue', you could do this:

DELETE
  FROM table1
 WHERE col1 = 'somevalue'

EDIT
To delete using a correlated subquery, please see the following example:

create table project (id int);
create table emp_project (id int, project_id int);

insert into project values (1);
insert into project values (2);
insert into emp_project values (100, 1);
insert into emp_project values (200, 1);

/* Delete any project record that doesn't have associated emp_project records */
DELETE
  FROM project
 WHERE NOT EXISTS
     (SELECT *
        FROM emp_project e
       WHERE e.project_id = project.id);


/* project 2 doesn't have any emp_project records, so it was deleted, now
   we have 1 project record remaining */
SELECT * FROM project;

Result:
id
1
dcp
  • 54,410
  • 22
  • 144
  • 164
  • oops...you made to look me fool :-) but i missed this point, ie. for subqueries DELETE FROM WHERE IN (SELECT FROM WHERE NOT IN (SELECT FROM GROUP BY ORDER BY ) This query takes more time when the records are high, my query is doing this using temp table will affect mysql's performance level or it will enhance if this is done using temp table. ie. get the subquery values and insert to a temp table and run a delete statement wher IN condition will be checking with select col1 from temp. – Sharpeye500 Jul 27 '10 at 17:22
  • @Sharpeye - Sorry, didn't intend to make you look the fool, I thought it was your real question. Anyway, it'd be good if you can post a data example, namely, show us the records that exist before, and the records you expect to be deleted. Then we'll be able to help more. – dcp Jul 27 '10 at 17:28
  • @Sharpeye - You can refer to my latest edit for how to delete using a correlated subquery. – dcp Jul 27 '10 at 17:58
0

Create a temp table with the values you want to delete, then join it to the table while deleting. In this example I have a table "Games" with an ID column. I will delete ids greater than 3. I will gather the targets in a temp table first so I can report on them later.

DECLARE @DeletedRows TABLE (ID int)

insert
    @DeletedRows
        (ID)
select
    ID
from
    Games
where
    ID > 3


DELETE
    Games
from
    Games g
join
    @DeletedRows x
    on x.ID = g.ID  
Carter Medlin
  • 11,857
  • 5
  • 62
  • 68
  • 1
    Thanks carter but will this affect mysql performance? for ex. say if you have 1000 users to your site, if all of the them start to create temp tables on their login, what will happen to table cache/table memory, it will increase correct? – Sharpeye500 Jul 27 '10 at 17:28
  • It is only creating a table in memory. It will use more resources than just deleting the rows normally, but if you want to report on the records deleted it is the only way. It is only using memory to store the IDs of records you are going to delete. – Carter Medlin Jul 27 '10 at 17:36
0

I have used group by aggregate with having clause and same table, where the query was like

DELETE 
FROM TableName
WHERE id in 
   (select implicitTable.id 
    FROM (
          SELECT id 
          FROM `TableName` 
          GROUP by id 
          HAVING count(id)>1
          ) as implicitTable
   )
-3

You can delete from same table. Delete statement is as follows

DELETE FROM table_name
WHERE some_column=some_value
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
YoK
  • 14,329
  • 4
  • 49
  • 67
-3

You mean something like:

DELETE FROM table WHERE someColumn = "someValue";

?

This is definitely possible, read about the DELETE syntax in the reference manual.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143