Как я могу удалить дубликаты строк?

Я пробовал это и отлично работал с моим управляемым bean-файлом JSF

ExecutorService executor = Executors.newFixedThreadPool(1);

@EJB
private IMaterialSvc materialSvc;

private void updateMaterial(Material material, String status,  Location position) {

    executor.execute(new Runnable() {
        public void run() {
            synchronized (position) {
                // TODO update material in audit? do we need materials in audit?
                int index = position.getMaterials().indexOf(material);
                Material m = materialSvc.getById(material.getId());
                m.setStatus(status);
                m = materialSvc.update(m);
                if (index != -1) {
                    position.getMaterials().set(index, m);
                }

            }
        }
    });

}

@PreDestroy
public void destory() {
    executor.shutdown();
}
1229
задан DineshDB 28 March 2018 в 10:48
поделиться

7 ответов

Принятие никакого аннулирует, Вы GROUP BY уникальные столбцы, и SELECT MIN (or MAX) RowId как строка для хранения. Затем просто удалите все, что не имело идентификатора строки:

DELETE FROM MyTable
LEFT OUTER JOIN (
   SELECT MIN(RowId) as RowId, Col1, Col2, Col3 
   FROM MyTable 
   GROUP BY Col1, Col2, Col3
) as KeepRows ON
   MyTable.RowId = KeepRows.RowId
WHERE
   KeepRows.RowId IS NULL

В случае, если у Вас есть GUID вместо целого числа, можно заменить

MIN(RowId)

с

CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))
1108
ответ дан Srini 28 March 2018 в 10:48
поделиться

От прикладного уровня (к сожалению). Я соглашаюсь, что надлежащий способ предотвратить дублирование на уровне базы данных с помощью уникального индекса, но в SQL Server 2005, индексу позволяют быть только 900 байтов, и мой varchar (2048), поле сдувает это.

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

-- given a table stories(story_id int not null primary key, story varchar(max) not null)
CREATE TRIGGER prevent_plagiarism 
ON stories 
after INSERT, UPDATE 
AS 
    DECLARE @cnt AS INT 

    SELECT @cnt = Count(*) 
    FROM   stories 
           INNER JOIN inserted 
                   ON ( stories.story = inserted.story 
                        AND stories.story_id != inserted.story_id ) 

    IF @cnt > 0 
      BEGIN 
          RAISERROR('plagiarism detected',16,1) 

          ROLLBACK TRANSACTION 
      END 

кроме того, varchar (2048) звуки, подозрительные мне (некоторые вещи в жизни составляют 2 048 байтов, но это довольно редко); разве это не должен действительно быть varchar (макс.)?

7
ответ дан Gidil 28 March 2018 в 10:48
поделиться

Вот другая хорошая статья о дубликаты удаления .

Это обсуждает почему его твердое: " SQL основан на алгебре отношений, и дубликаты не могут произойти в алгебре отношений, потому что дубликаты не позволяются в наборе. "

временное решение для таблицы и два mysql примера.

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

12
ответ дан Craig 28 March 2018 в 10:48
поделиться

Ну конечно. Используйте временную таблицу. Если Вы хотите сингл, not-very-performant оператор, который "работает", можно пойти с:

DELETE FROM MyTable WHERE NOT RowID IN
    (SELECT 
        (SELECT TOP 1 RowID FROM MyTable mt2 
        WHERE mt2.Col1 = mt.Col1 
        AND mt2.Col2 = mt.Col2 
        AND mt2.Col3 = mt.Col3) 
    FROM MyTable mt)

В основном, для каждой строки в таблице, подвыбор находит лучший RowID всех строк, которые точно похожи на строку на рассмотрении. Таким образом, Вы заканчиваете со списком RowIDs, которые представляют "исходные" недублированные строки.

12
ответ дан Harrison Brock 28 March 2018 в 10:48
поделиться

Существует хорошая статья о дубликаты удаления на Microsoft Support site. Это довольно консервативно - они сделали, чтобы Вы сделали все на отдельных шагах - но это должно работать хорошо против больших таблиц.

я использовал самосоединения, чтобы сделать это в прошлом, хотя это мог, вероятно, быть prettied с пунктом НАЛИЧИЯ:

DELETE dupes
FROM MyTable dupes, MyTable fullTable
WHERE dupes.dupField = fullTable.dupField 
AND dupes.secondDupField = fullTable.secondDupField 
AND dupes.uniqueField > fullTable.uniqueField
141
ответ дан Ivan Yurchenko 28 March 2018 в 10:48
поделиться
  1. Создать новую пустую таблицу с той же структурой

  2. Выполнить запрос, подобный этому

     INSERT INTO tc_category1
    ВЫБРАТЬ *
    ОТ tc_category
    GROUP BY category_id, application_id
    Имея количество (*)> 1
    
  3. Затем выполните этот запрос

     INSERT INTO tc_category1
    ВЫБРАТЬ *
    ОТ tc_category
    GROUP BY category_id, application_id
    HAVING count (*) = 1
    
9
ответ дан 19 December 2019 в 20:15
поделиться

У меня была таблица, в которой мне нужно было сохранить неповторяющиеся строки. Я не уверен в скорости или эффективности.

DELETE FROM myTable WHERE RowID IN (
  SELECT MIN(RowID) AS IDNo FROM myTable
  GROUP BY Col1, Col2, Col3
  HAVING COUNT(*) = 2 )
11
ответ дан 19 December 2019 в 20:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: