2014-02-17 5 views
0

Я ищу простой подход для удаления СОПРЕДЕЛЬНЫХ повторяющихся записей из таблицы, как это:SQL Server. Как удалить СОПРЕДЕЛЬНЫЕ дубликаты записей

PatientID|STATE 
1|A 
1|A 
1|B 
1|B 
1|C 
1|A 
1|C 
1|C 
1|B 
2|A 
... 

То есть, из вышесказаннога я хочу сохранить heighest ранжированного письмо от каждого блок букв данного типа. Пример:

 
PatientID|STATE 
1|A 
1|B 
1|C 
1|A 
1|C 
1|B 
2|A 
... 

У меня нет других доступных колонок. Я знаю о функциях ROW_NUMBER() OVER (PARTITION BY ..), но не вижу, как это можно применить здесь

+4

Где что заказ пришел из (один в свой первый результат)? У вас где-то есть поле даты? Поле идентификации? –

+0

Если у вас нет других доступных столбцов, вы не можете делать то, что хотите. Таблицы SQL по своей сути неупорядочены. Вы можете сделать 'select *' и получить результаты в разных заказах в разное время. –

+0

Я должен был быть более ясным. Существует порядок значений состояния для данного идентификатора пациента, который по существу является датой, но для этой цели я знаю просто порядок, который я могу, например. представляют новый столбец идентификационного идентификатора – user1657216

ответ

0

SQL Server имеет хорошую возможность иметь обновляемые CTE. Предполагая, что у вас есть поле id или поле даты и времени, чтобы указать порядок, вы можете идентифицировать «группы» соседних записей, используя трюк row_number() - разницу между номером строки в заданном и в пределах данной комбинации PatientId, state. Тогда просто использовать эту группу, чтобы перечислить значения и сохранить первый или последний:

with todelete as (
     select t.*, row_number() over (partition by Patientid, state, grp order by id) as seqnum 
     from (select t.*, 
        (row_number() over (partition by PatientId order by id) - 
        row_number() over (partition by PatientId, state order by id) 
        ) as grp 
      from table t 
      ) t 
    ) 
delete from todelete 
    where seqnum > 1; 
+0

_ «У меня нет других доступных столбцов. Я знаю о функциях ROW_NUMBER() OVER (PARTITION BY ..), но не вижу, как это можно применить здесь» _ –

+0

Aha! Очень умное использование функции row_number(). Это делает то, что я искал. Я переместил его из рамки CTE, так как я, вероятно, фактически не удалю дубликаты в реальной реализации, но разрешаю это как флаги фильтрации. Другое дело, что я считаю, что раздел во внешнем выражении select должен быть равен (PID, state, grp) вместо (id, state, grp) – user1657216

0

Я думаю, что ниже запрос поможет вам

SElect PatientID,State,COUNT(*) AS TOTAL INTO #Temp2 from table GROUP by PatientID,State 
HAVING COUNT(*) > 1 

DELETE FROM table 
FROM table a INNER JOIN (
SElect PatientID,State,COUNT(*) AS TOTAL from table GROUP by PatientID,State 
HAVING COUNT(*) > 1) b ON a.PatientID = b.PatientID AND a.State = b.State 

INSERT INTO table SELECT PatientID,State FROM #Temp2 
Смежные вопросы