2012-11-17 26 views
4

我有一個表是這樣的:SQL刪除行與同組值

ID, ItemsID 
1 2                  
1 3  
1 4 
2 3 
2 4 
2 2 

我想刪除的元組像ID=2因爲2,3,4都一樣在我的處境3,4,2

我該如何使用SQL?

+0

原始標題是混亂的,讓我想關於重複行的另一個問題。在數據庫理論中,元組與行相同。 – madth3

+0

哪個版本的Oracle? – APC

+0

你的意思是你想刪除ID = 2和keepID = 1,因爲ID = 2的所有行都具有與那些行ID = 1相同的itemsID值?另外:您的聲明似乎表明這些行具有實際的順序,但它們沒有。您也可以按照4,3,2或2,4,3或3,2,4的順序獲取行,只要您沒有聲明順序即可。 –

回答

1

對不起,我沒有及時看到Oracle標籤。但是,我將離開MySQL解決方案以供參考。 Apparently在某些Oracle版本中有類似GROUP_CONCAT()的東西。


它可能不是最完美的解決方案,但這將做的工作:

DELETE FROM t WHERE ID IN (
    SELECT ID 
    FROM (SELECT ID, GROUP_CONCAT(ItemsID ORDER BY ItemsID) AS tuple FROM t GROUP BY ID) AS tuples 
    WHERE EXISTS (
    SELECT TRUE 
    FROM (SELECT ID, GROUP_CONCAT(ItemsID ORDER BY ItemsID) AS tuple FROM t GROUP BY ID) tuples2 
    WHERE tuples2.tuple = tuples.tuple 
    AND tuples2.ID < tuples.ID 
) 
) 

SQLfiddle

您可能要調整group_concat_max_len

+0

好主意 - 儘管它不直接適用於Oracle。 –

0

這是我能拿出最好的,但不知何故,我有一種感覺,必須有一個簡單的解決方案:

delete from items 
where id in (
    select id 
    from (
    with counts as (
     select id, 
       count(*) as cnt 
     from items 
     group by id 
    ) 
    select c1.id, row_number() over (order by c1.id) as rn 
    from counts c1 
     join counts c2 
     on c1.id <> c2.id and c1.cnt = c2.cnt 
    and not exists (select i1.itemsid 
        from items i1 
        where i1.id = c1.id 
        minus 
        select i2.itemsid 
        from items i2 
        where i2.id = c2.id) 
) t 
    where rn <> 1 
); 

它將爲任意數量的itemsid價值的工作。

rn <> 1結合在窗口定義中的升序將保持表中最小的id(在你的情況下是1)。如果要保留最高ID值,則需要將排列順序更改爲over (order by c1.id desc)

1

另一種方法。 Oracle 10gR1或更高版本。在這個例子中,我們有ItemsID的值ID s 1,2,6,另一個3和另一個4和5.所以我們要刪除ID秒2,6和5,因爲它們似乎是重複的,由表示每一組特定IDItemsID元素作爲嵌套表,並且使用multiset except操作,以確定是否一個組中的元素是相同的:

-- set-up 
SQL> create table tb_table(
    2 id number, 
    3 itemsid number); 

Table created 

SQL> insert into tb_table(id, itemsid) 
    2 select 1, 2 from dual union all 
    3 select 1, 3 from dual union all 
    4 select 1, 4 from dual union all 
    5 select 2, 4 from dual union all 
    6 select 2, 3 from dual union all 
    7 select 2, 2 from dual union all 
    8 select 3, 2 from dual union all 
    9 select 3, 3 from dual union all 
10 select 3, 6 from dual union all 
11 select 3, 4 from dual union all 
12 select 4, 1 from dual union all 
13 select 4, 2 from dual union all 
14 select 4, 3 from dual union all 
15 select 5, 1 from dual union all 
16 select 5, 2 from dual union all 
17 select 5, 3 from dual union all 
18 select 6, 2 from dual union all 
19 select 6, 4 from dual union all 
20 select 6, 3 from dual; 

19 rows inserted 

SQL> commit; 

Commit complete 

SQL> create or replace type t_numbers as table of number; 
    2/

Type created 

-- contents of the table 
SQL> select * 
    2 from tb_table; 

     ID ITEMSID 
---------- ---------- 
     1   2 
     1   3 
     1   4 
     2   4 
     2   3 
     2   2 
     3   2 
     3   3 
     3   6 
     3   4 
     4   1 
     4   2 
     4   3 
     5   1 
     5   2 
     5   3 
     6   2 
     6   4 
     6   3 


19 rows selected 

SQL> delete from tb_table 
    2 where id in (with DataGroups as(
    3     select id 
    4      , grp 
    5      , (select count(*) from table(grp)) cnt 
    6     from (select id 
    7        , cast(collect(itemsid) as t_numbers) grp 
    8       from tb_table 
    9       group by id 
10       ) 
11     ) 
12     select distinct id2 
13      from (select dg1.id as id1 
14         , dg2.id as id2 
15         , (dg1.grp multiset except dg2.grp) res 
16         , dg1.cnt 
17        from DataGroups Dg1 
18       cross join DataGroups Dg2 
19       where dg1.cnt = dg2.cnt 
20       order by dg1.id 
21       ) t 
22     where res is empty 
23      and id2 > id1 
24     ) 
25 ; 

9 rows deleted 

SQL> select * 
    2 from tb_table; 

     ID ITEMSID 
---------- ---------- 
     1   2 
     1   3 
     1   4 
     3   2 
     3   3 
     3   6 
     3   4 
     4   1 
     4   2 
     4   3 

10 rows selected