Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete from table A joining on table A in Redshift

I am trying to write the following MySQL query in PostgreSQL 8.0 (specifically, using Redshift):

DELETE t1 FROM table t1
LEFT JOIN table t2 ON (
    t1.field   = t2.field AND
    t1.field2  = t2.field2
)
WHERE t1.field > 0

PostgreSQL 8.0 does not support DELETE FROM table USING. The examples in the docs say that you can reference columns in other tables in the where clause, but that doesn't work here as I'm joining on the same table I'm deleting from. The other example is a subselect query, but the primary key of the table I'm working with has four columns so I can't see a way to make that work either.

like image 405
moinudin Avatar asked Apr 30 '14 16:04

moinudin


People also ask

How do I DELETE data from Redshift table?

To delete rows in a Redshift table, use the DELETE FROM statement: DELETE FROM products WHERE product_id=1; The WHERE clause is optional, but you'll usually want it, unless you really want to delete every row from the table.

Is DELETE allowed in JOIN?

It is totally possible to use JOIN and multiple tables in the DELETE statement.

How can I DELETE row data from a table?

Right-click in a table cell, row, or column you want to delete. On the menu, click Delete Cells. To delete one cell, choose Shift cells left or Shift cells up. To delete the row, click Delete entire row.


2 Answers

Amazon Redshift may be based on Postgres 8.0, but is a very much different thing. I don't use it, but the manual informs, that the USING clause is supported in DELETE statements:

Just use the modern form:

DELETE FROM tbl
USING  tbl t2
WHERE  t2.field  = tbl.field
AND    t2.field2 = tbl.field2
AND    t2.pkey  <> tbl.pkey    -- exclude self-join
AND    tbl.field > 0;

This is assuming JOIN instead of LEFT JOIN in your MySQL statement, which would not make any sense. I also added the condition AND t2.pkey <> t1.pkey, to make it a useful query. This excludes rows joining itself. pkey being the primary key column.

What this query does:
Delete all rows where at least one other row exists in the same table with the same not-null values in field and field2. All such duplicates are deleted without leaving a single row per set.

To keep (for example) the row with the smallest pkey per set of duplicates, use t2.pkey < t2.pkey.

An EXISTS semi-join (as @wilplasser already hinted) might be a better choice, especially if multiple rows could be joined (a row can only be deleted once anyway):

DELETE FROM tbl
WHERE  field > 0
AND    EXISTS (
   SELECT 1
   FROM   tbl t2
   WHERE  t2.field  = tbl.field
   AND    t2.field2 = tbl.field2
   AND    t2.pkey  <> tbl.pkey 
   );
like image 113
Erwin Brandstetter Avatar answered Sep 27 '22 19:09

Erwin Brandstetter


I don't understand the mysql syntax, but you probably want this:

DELETE FROM mytablet1
WHERE t1.field > 0
   -- don't need this self-join if {field,field2}
   -- are a candidate key for mytable
   -- (in that case, the exists-subquery would detect _exactly_ the
   -- same tuples as the ones to be deleted, which always succeeds)
-- AND EXISTS (
--     SELECT *
--     FROM mytable t2 
--     WHERE t1.field = t2.field
--     AND t1.field2  = t2.field2
--    )
    ;

Note: For testing purposes, you can replace the DELETE keyword by SELECT * or SELECT COUNT(*), and see which rows would be affected by the query.

like image 31
wildplasser Avatar answered Sep 27 '22 21:09

wildplasser