Справка по удалению дубликатов SQL-запросов

Мне нужно удалить полудубликаты записей из следующей таблицы

ID      PID      SCORE
1       1        50
2       33       20
3       1        90
4       5        55
5       7        11
6       22       34

Для любых существующих дубликатов PID я хочу удалить запись с наименьшей оценкой. В приведенном выше примере ID 1 будет удален. Я пытаюсь придумать способ сделать это без использования циклов, но я действительно борюсь.

Любая помощь будет оценена по достоинству.

Спасибо


person Gavin    schedule 12.10.2009    source источник


Ответы (3)


WITH    q AS
        (
        SELECT  *, ROW_NUMBER() OVER (PARTITION BY pid ORDER BY score) AS rn
        FROM    mytable
        )
DELETE
FROM    q
WHERE   rn = 1

Чтобы оставить результаты, не имеющие дубликатов:

WITH    q AS
        (
        SELECT  *,
                ROW_NUMBER() OVER (PARTITION BY pid ORDER BY score) AS rn,
                COUNT(*) OVER (PARTITION BY pid) AS cnt
        FROM    mytable
        )
DELETE
FROM    q
WHERE   rn = 1
        AND cnt > 1
person Quassnoi    schedule 12.10.2009
comment
Не будет ли это также удалять записи, у которых нет дубликатов? - person Gavin; 12.10.2009
comment
разве вы не должны разбивать по pid, упорядочивать по счету и удалять, где номер строки = 2? - person Preets; 12.10.2009
comment
@op хочет удалить только идентификатор с наименьшей оценкой, а не все остальные. - person Quassnoi; 12.10.2009
comment
@Mark: да, я пропустил, что @op хотят удалить самый низкий балл, а не самый низкий идентификатор. - person Quassnoi; 12.10.2009

попробуй это..

    declare @tt table(id int, pid int,score int)
    insert into @tt
    select 1,1,50 union all
    select 2,33,50 union all
    select 8,33,80 union all
    select 3,1,90 union all
    select 4,5,50 union all
    select 5,5,10 union all
    select 6,6,10 union all
    select 7,6,50  
    ---------   
    delete from @tt where id in (
    select t1.id from @tt t1 inner join
    (
        select  MIN(score) tScore,pid tPid from @tt where pid in 
        (select  pid from @tt group by pid having count (pid) > 1) group by pid 
    ) t2 on t1.pid=t2.tPid and t1.score=t2.tScore)

    select * from @tt
person RameshVel    schedule 12.10.2009

Я не вижу ваш запрос, поэтому я составил этот пример...

SELECT
    PID,
    MAX(Score)
FROM
    tblTable
GROUP BY
    PID
person Fenton    schedule 12.10.2009
comment
Это выбирает те, которые хочет OP, а не удаляет другие - person mmmmmm; 12.10.2009