Forum Stats

  • 3,839,819 Users
  • 2,262,538 Discussions
  • 7,901,063 Comments

Discussions

help required to wrire a query.

Roy4321
Roy4321 Member Posts: 305 Bronze Badge
edited Dec 8, 2009 6:15AM in SQL & PL/SQL
Hi,
I have the below data

TableA

name----id----status
mat----123---- 1
mat----123---- 2 -- to be deleted
mat----123---- 2 -- to be deleted
sam----456---- 2
sam----456---- 2 -- to be deleted
dan----789---- 1
dan----789---- 1 -- to be deleted
dan----789---- 2 -- to be deleted
pan----111---- 1


can someone give me an idea how to write a query that delletes the records marked as "-- to be deleted"

Thanks,
Mathew

Edited by: [email protected] on Dec 4, 2009 12:21 AM
«1

Answers

  • MaheshKaila
    MaheshKaila Member Posts: 310
    DELETE FROM table_name t1
    WHERE (EXISTS
              (SELECT ROWID
               FROM table_name t2
               WHERE t1.name = t2.name
                     AND t1.id = t2.id
                     AND t1.status = t2.status
                     AND t2.ROWID > t1.ROWID))
                     
                     
    DELETE FROM table_name t1
    WHERE (EXISTS
              (SELECT ROWID
               FROM table_name t2
               WHERE t1.name = t2.name
                     AND t1.id = t2.id
                     AND t1.status <> '1'
                     AND t2.ROWID > t1.ROWID))                 
    Regards,
    Mahesh Kaila
  • 21205
    21205 Member Posts: 6,168 Gold Trophy
    What is the logic behind this? Why are those records identified as to be deleted?
  • 523888
    523888 Member Posts: 208
    I think this might work
    delete from t where rowid not in 
    (select min(rowid) from t 
    group by name,id)
  • Roy4321
    Roy4321 Member Posts: 305 Bronze Badge
    Those are actually duplicate records ...only it differs in status...but if there is a record with status as 1 i want to keep that record and delete the rest..but if records are only present with status 2 then the first record with status 2 needs to be deleted --these are for each ID.

    hope this helps!!
  • Roy4321
    Roy4321 Member Posts: 305 Bronze Badge
    this will not work...as i will need to keep the record with status as 1 if it exists.
  • 21205
    21205 Member Posts: 6,168 Gold Trophy
    something like?
    SQL> create table test
      2  as
      3  select 'mat' name, 123 id, 1 status from dual union all
      4  select 'mat' name, 123 id, 2 status from dual union all -- to be deleted
      5  select 'mat' name, 123 id, 2 status from dual union all -- to be deleted
      6  select 'sam' name, 456 id, 2 status from dual union all
      7  select 'sam' name, 456 id, 2 status from dual union all -- to be deleted
      8  select 'dan' name, 789 id, 1 status from dual union all
      9  select 'dan' name, 789 id, 1 status from dual union all -- to be deleted
     10  select 'dan' name, 789 id, 2 status from dual union all -- to be deleted
     11  select 'pan' name, 111 id, 1 status from dual
     12  /
    
    Table created.
    
    SQL> 
    SQL> delete from test
      2   where rowid in 
      3     (select rid
      4        from (
      5           select rowid rid
      6                , row_number() over (partition by name, id
      7                                         order by status
      8                                    ) rn
      9             from test
     10        )
     11       where rn > 1
     12     )
     13  /
    
    5 rows deleted.
    
    SQL> 
    SQL> select *
      2    from test
      3  /
    
    NAM         ID     STATUS
    --- ---------- ----------
    mat        123          1
    sam        456          2
    dan        789          1
    pan        111          1
    
    SQL> 
    SQL> drop table test purge
      2  /
    
    Table dropped.
    
    SQL> 
  • 523888
    523888 Member Posts: 208
    then what about this row that you mentioned

    sam----456---- 2
    sam----456---- 2 -- to be deleted
  • Roy4321
    Roy4321 Member Posts: 305 Bronze Badge
    Thanks Alex...that works!!
  • Roy4321
    Roy4321 Member Posts: 305 Bronze Badge
    if i am correct the query you wrote will take the min rowid and delete the rest..but if min(rowid) is not for status 1 then this gets deleted too...
  • 523888
    523888 Member Posts: 208
    create table test2
    as
    (select 'mat' name, 123 id, 1 status from dual union all
    select 'mat' name, 123 id, 2 status from dual union all -- to be deleted
    select 'mat' name, 123 id, 2 status from dual union all -- to be deleted
    select 'sam' name, 456 id, 2 status from dual union all
    select 'sam' name, 456 id, 2 status from dual union all -- to be deleted
    select 'dan' name, 789 id, 1 status from dual union all
    select 'dan' name, 789 id, 1 status from dual union all -- to be deleted
    select 'dan' name, 789 id, 2 status from dual union all -- to be deleted
    select 'pan' name, 111 id, 1 status from dual
    );
    
    select * from test2;
    
    NAME	ID	STATUS
    mat	123	1
    mat	123	2
    mat	123	2
    sam	456	2
    sam	456	2
    dan	789	1
    dan	789	1
    dan	789	2
    pan	111	1
    
    delete from test2 where rowid not in 
    (select min(rowid) from test2
    group by name,id);
    
    5 rows deleted
    
    select * from test2;
    
    NAME	ID	STATUS
    mat	123	1
    sam	456	2
    dan	789	1
    pan	111	1
This discussion has been closed.