Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using WITH + DELETE clause in a single query in postgresql

I have the following table structure, for a table named listens with PRIMARYKEY on (uid,timestamp)

     Column     |            Type             |                      Modifiers                       
----------------+-----------------------------+------------------------------------------------------    
 id             | integer                     | not null default nextval('listens_id_seq'::regclass)
 uid            | character varying           | not null
 date           | timestamp without time zone | 
 timestamp      | integer                     | not null
 artist_msid    | uuid                        | 
 album_msid     | uuid                        | 
 recording_msid | uuid                        | 
 json           | character varying           | 

I need to remove all the entries for a particular user (uid) which are older than the max timestamp, say max is 123456789 (in seconds) and delta is 100000, then, all records older than max-100000.

I have managed to create a query when the table contains a single user but i am unable to formulate it to work for every user in the database. This operation needs to be done for every user in the database.

WITH max_table as (
    SELECT max(timestamp) - 10000 as max 
    FROM listens 
    GROUP BY uid) 
DELETE FROM listens 
WHERE timestamp < (SELECT max FROM max_table);

Any solutions?

like image 665
Pinkesh Badjatiya Avatar asked May 14 '16 09:05

Pinkesh Badjatiya


People also ask

Can we use with clause in PostgreSQL?

You can use data-modifying statements (INSERT, UPDATE or DELETE) in WITH. This allows you to perform several different operations in the same query.

How do I delete multiple records in PostgreSQL?

First, specify the table from which you want to delete data in the DELETE FROM clause. Second, specify which rows to delete by using the condition in the WHERE clause. The WHERE clause is optional. However, if you omit it, the DELETE statement will delete all rows in the table.

Can we use join IN delete query in PostgreSQL?

Introduction to PostgreSQL DELETE JOIN. It is used to delete table records or rows. We can join two tables with “using” keyword in PostgreSQL, after table join it will delete the specified rows from the specified table. It is used to delete the rows using with and without where conditions.

Can we use WHERE clause with delete in SQL?

DELETE Syntax Notice the WHERE clause in the DELETE statement. The WHERE clause specifies which record(s) should be deleted. If you omit the WHERE clause, all records in the table will be deleted!


2 Answers

I think all you need, is to make this a co-related subquery:

WITH max_table as (
    SELECT uid, max(timestamp) - 10000 as mx
    FROM listens 
    GROUP BY uid
) 
DELETE FROM listens 
WHERE timestamp < (SELECT mx
                   FROM max_table 
                   where max_table.uid = listens.uid);

Btw: timestamp is a horrible name for a column, especially one that doesn't contain a timestamp value. One reason is because it's also a keyword but more importantly it doesn't document what that column contains. A registration timestamp? An expiration timestamp? A last active timestamp?

like image 200
a_horse_with_no_name Avatar answered Oct 14 '22 11:10

a_horse_with_no_name


Alternatively, you could avoid the MAX() by using an EXISTS()

DELETE FROM listens d
WHERE EXISTS (
        SELECT * FROM listens x
        WHERE x.uid = d.uid
        AND x.timestamp >= d.timestamp + 10000 
        );  

BTW: timestamp is an ugly name for a column, since it is also a typename.

like image 26
wildplasser Avatar answered Oct 14 '22 09:10

wildplasser