2009-11-23 3 views
0

Я ищу запрос на выбор максимально возможной даты (a datetime) и сохраните его id и row_id. Желание состоит из DELETE строк в исходной таблице.TSQL: удалите дубликаты на основе max (date)

Источник данных

id  date   row_id(unique) 
1  11/11/2009 1 
1  12/11/2009 2 
1  13/11/2009 3 
2  1/11/2009  4 

Ожидаемые Выжившие

1  13/11/2009 3 
2  1/11/2009  4 

Что запрос я должен был бы достичь результатов, которые я ищу?

+1

Вы сказали удалить дубликаты, но, видимо, вы удаляете все даты между min и max - можете ли вы уточнить? – Amarghosh

ответ

2

Проверено на PostgreSQL:

delete from table where (id, date) not in (select id, max(date) from table group by id); 
1

Существуют различные способы сделать это, но основная идея та же:
- Indentify строки, которые вы хотите сохранить
- Сравнить каждую строку в таблице на те, которые вы хотите сохранить
- Удалите все, что не соответствует

DELETE 
    [source] 
FROM 
    yourTable AS [source] 
LEFT JOIN 
    yourTable AS [keep] 
     ON [keep].id = [source].id 
     AND [keep].date = (SELECT MAX(date) FROM yourTable WHERE id = [keep].id) 
WHERE 
    [keep].id IS NULL 


DELETE 
    [yourTable] 
FROM 
    [yourTable] 
LEFT JOIN 
(
    SELECT id, MAX(date) AS date FROM yourTable GROUP BY id 
) 
    AS [keep] 
     ON [keep].id = [yourTable].id 
     AND [keep].date = [yourTable].date 
WHERE 
    [keep].id IS NULL 


DELETE 
    [source] 
FROM 
    yourTable AS [source] 
WHERE 
    [source].row_id != (SELECT TOP 1 row_id FROM yourTable WHERE id = [source].id ORDER BY date DESC) 


DELETE 
    [source] 
FROM 
    yourTable AS [source] 
WHERE 
    NOT EXISTS (SELECT id FROM yourTable GROUP BY id HAVING id = [source].id AND MAX(date) != [source].date) 
0

Поскольку вы используете SQL Server 2000, you'er не в состоянии использовать ряд на технику создания последовательности и определить верхнюю строку для каждого уникального идентификатора.

Итак, ваша предлагаемая методика заключается в использовании столбца datetime, чтобы получить верхнюю 1 строку для удаления дубликатов. Это может сработать, но есть вероятность, что вы все равно получите дубликаты с одинаковым значением даты и времени. Но это достаточно легко проверить.

Сначала проверьте предположение о том, что все строки являются уникальными на основе идентификаторов и столбцов дат:

CREATE TABLE #TestTable (rowid INT IDENTITY(1,1), thisid INT, thisdate DATETIME) 
INSERT INTO #TestTable (thisid,thisdate) VALUES (1, '11/11/2009') 
INSERT INTO #TestTable (thisid,thisdate) VALUES (1, '12/11/2009') 
INSERT INTO #TestTable (thisid,thisdate) VALUES (1, '12/12/2009') 
INSERT INTO #TestTable (thisid,thisdate) VALUES (2, '1/11/2009') 
INSERT INTO #TestTable (thisid,thisdate) VALUES (2, '1/11/2009') 

SELECT COUNT(*) AS thiscount 
FROM #TestTable 
GROUP BY thisid, thisdate 
HAVING COUNT(*) > 1 

Этот пример возвращает значение 2 - о том, что вы до сих пор в конечном итоге с дубликатами даже после того, как с использованием даты для удаления дубликатов. Если вы вернетесь 0, то вы доказали, что ваш предлагаемый метод будет работать.

При удалении данных о производстве, я думаю, что следует принять некоторые меры предосторожности и проверить до и после. Вы должны создать таблицу для хранения строк, которые вы планируете удалить, чтобы вы могли легко их восстановить, если вам нужно, чтобы после выполнения инструкции удаления.

Кроме того, рекомендуется заранее знать, сколько строк вы планируете удалить, чтобы вы могли проверить счет до и после - и вы можете оценить величину операции удаления. На основании того, сколько строк будет затронуто, вы можете планировать, когда запускать операцию.

Для проверки перед процессом удаления дубликатов найдите вхождения.

-- Get occurrences of duplicates 
SELECT COUNT(*) AS thiscount 
FROM 
#TestTable 
GROUP BY thisid 
HAVING COUNT(*) > 1 
ORDER BY thisid 

Это дает вам строки с более чем одной строкой с одинаковым идентификатором. Захватите строки из этого запроса во временную таблицу и затем запустите запрос с помощью СУММ, чтобы получить общее количество строк, которые не уникальны на основе вашего ключа.

Чтобы получить количество строк, которые вы планируете удалить, вам потребуется количество строк, дублирующихся на основе вашего уникального ключа, и количество отдельных строк на основе вашего уникального ключа. Вычитайте отдельные строки из числа вхождений. Все это довольно просто, поэтому я оставлю вас.

0

Попробуйте

declare @t table (id int, dt DATETIME,rowid INT IDENTITY(1,1)) 
INSERT INTO @t (id,dt) VALUES (1, '11/11/2009') 
INSERT INTO @t (id,dt) VALUES (1, '11/12/2009') 
INSERT INTO @t (id,dt) VALUES (1, '11/13/2009') 
INSERT INTO @t (id,dt) VALUES (2, '11/01/2009') 

запрос:

delete from @t where rowid not in(
select t.rowid from @t t 
inner join(
select MAX(dt)maxdate 
from @t 
group by id) X 
on t.dt = X.maxdate) 

select * from @t 

Выход:

id dt rowid 
1 2009-11-13 00:00:00.000 3 
2 2009-11-01 00:00:00.000 4 
0
delete from temp where row_id not in (
     select t.row_id from temp t 
     right join 
     (select id,MAX(dt) as dt from temp group by id) d 
     on t.dt = d.dt and t.id = d.id) 

Я испытал этот ответ ..

0
INSERT INTO #t (id,dt) VALUES (1, '11/11/2009') 
INSERT INTO #t (id,dt) VALUES (1, '11/12/2009') 
INSERT INTO #t (id,dt) VALUES (1, '11/13/2009') 
INSERT INTO #t (id,dt) VALUES (2, '11/01/2009') 
select * from #t 

;WITH T AS(
select dense_rank() over(partition by id order by dt desc)NO,DT,ID,rowid from #t) 

DELETE T WHERE NO>1 
Смежные вопросы