SQL для удаления повторяющихся записей с некоторыми общими значениями полей?

Рассмотрим таблицу со следующей схемой:

id, location, starred

Есть много записей с одним и тем же местоположением:

id | location | starred
-----------------------
1     rome      yes
2     rome      no
3     rome      no
4     milan     yes
5     milan     no
6     bozen     no

Я хочу иметь не более одной записи для каждого местоположения. И учитывая выбор между записью, отмеченной звездочкой, и записью, не отмеченной звездочкой, я хочу звездную запись. Итак, какой sql создаст эту таблицу:

id | location | starred
-----------------------
1     rome      yes
4     milan     yes
6     bozen     no

Я подозреваю, что это можно сделать с помощью некоторых виртуальных таблиц или «представлений».

DELETE FROM table
GROUP BY location, 

person simpatico    schedule 27.06.2012    source источник
comment
Итак, вы хотите выбрать в схеме только разные города, и если есть дубликаты, вам нужен тот, у которого «звездочка» = да?   -  person vandershraaf    schedule 27.06.2012
comment
Да, возможно, создание материализованного представления этого запроса на выборку.   -  person simpatico    schedule 27.06.2012


Ответы (4)


Если [started] может быть только да или нет, то это должно работать:

create table data
(
id int identity(1,1),
location varchar(50),
[started] varchar(3)
)

insert into data select 'Rome', 'Yes'
insert into data select 'Rome', 'No'
insert into data select 'Rome', 'No'
insert into data select 'Milan', 'Yes'
insert into data select 'Milan', 'No'
insert into data select 'Bozen', 'No'

WITH locationsRanked (id, location, [started], rank)
AS
(
    select min(Id), location, [started],
    RANK() OVER (PARTITION BY location  ORDER BY location, [started] DESC) AS Rank
    from data
    group by location, [started]
)
select * from locationsRanked where Rank = 1
order by id
person Void Ray    schedule 27.06.2012

Используйте аналитические функции для удаления дубликатов. Следующий код генерирует местоположение на основе row_number и сортирует по отмеченному звездочкой описанию (поэтому да идет первым)

 delete from mytable2 where id in ( 
select id from
( select  id, location,starred,row_number() over ( partition by location order by location, starred desc) row_num 
  from mytable2
) where row_num >1
)
person Ramesh Manni    schedule 27.06.2012
comment
Это будет характерно для MS SQL Server. Однако идеальное решение для этого. - person Philip Kelley; 27.06.2012

Если вы просто хотите извлечь данные, должно работать что-то вроде этого:

select
    [table].*
from
    [table]
    inner join (select 
                    MIN(id) as id, 
                    location 
                from 
                    [table] 
                group by location) as data
        on [table].id = data.id

Очевидно, вы также можете использовать результаты этого (или аналогичного) запроса, чтобы определить список идентификаторов для удаления.

person Dave    schedule 27.06.2012
comment
вы игнорируете отмеченное звездочкой ограничение - person simpatico; 27.06.2012

Я думаю, что это может помочь вам:

http://www.w3schools.com/sql/sql_distinct.asp

person Robuust    schedule 27.06.2012