Подтвердить что ты не робот

Как я могу удалить одну из двух совершенно одинаковых строк?

Я очищаю таблицу базы данных без первичного ключа (знаю, я знаю, о чем они думали?). Я не могу добавить первичный ключ, потому что в столбце будет дубликат, который станет ключом. Дублированное значение получается из одной из двух строк, которые во всех отношениях одинаковы. Я не могу удалить строку через графический интерфейс (в этом случае MySQL Workbench, но я ищу агностический подход к базе данных), потому что он отказывается выполнять задачи на таблицах без первичных ключей (или, по крайней мере, столбца UQ NN), и Я не могу добавить первичный ключ, потому что в столбце будет дубликат, который станет ключом. Дублированное значение происходит от одного...

Как удалить одного из близнецов?

4b9b3361

Ответ 1

Один из вариантов решения вашей проблемы - создать новую таблицу с той же схемой, а затем выполните следующие действия:

INSERT INTO new_table (SELECT DISTINCT * FROM old_table)

а затем просто переименуйте таблицы.

Разумеется, вам потребуется примерно такое же пространство, что и для вашей таблицы, для этого требуется запасной на вашем диске!

Это неэффективно, но это невероятно просто.

Ответ 2

SET ROWCOUNT 1
DELETE FROM [table] WHERE ....
SET ROWCOUNT 0

Это приведет к удалению только одной из двух одинаковых строк

Ответ 3

Обратите внимание, что MySQL имеет собственное расширение DELETE, которое DELETE ... LIMIT, которое работает обычным способом, который вы ожидаете от LIMIT: http://dev.mysql.com/doc/refman/5.0/en/delete.html

Параметр LIMIT row_count, специфичный для MySQL, для DELETE указывает серверу максимальное количество строк, подлежащих удалению, до того, как элемент управления будет возвращен клиент. Это можно использовать для обеспечения того, чтобы данный оператор DELETE не занимает слишком много времени. Вы можете просто повторить DELETE до тех пор, пока количество затронутых строк будет меньше, чем значение LIMIT значение.

Следовательно, вы можете использовать DELETE FROM some_table WHERE x="y" AND foo="bar" LIMIT 1; отметить, что нет простого способа сказать "удалить все, кроме одного", - просто продолжайте проверять, есть ли у вас дубликаты строк.

Ответ 4

Для PostgreSQL вы можете сделать это:

DELETE FROM tablename
WHERE id IN (SELECT id
          FROM (SELECT id, ROW_NUMBER() 
               OVER (partition BY column1, column2, column3 ORDER BY id) AS rnum
               FROM tablename) t
          WHERE t.rnum > 1);

column1, column2, column3 будет набор столбцов, которые имеют повторяющиеся значения.

Ссылка здесь.

Ответ 5

delete top (1) работает на Microsoft SQL Server (T-SQL).

Ответ 6

Это можно выполнить с помощью функции CTE и ROW_NUMBER(), как показано ниже:

/* Sample Data */
    CREATE TABLE #dupes (ID INT, DWCreated DATETIME2(3))

    INSERT INTO #dupes (ID, DWCreated) SELECT 1, '2015-08-03 01:02:03.456'
    INSERT INTO #dupes (ID, DWCreated) SELECT 2, '2014-08-03 01:02:03.456'
    INSERT INTO #dupes (ID, DWCreated) SELECT 1, '2013-08-03 01:02:03.456'

/* Check sample data - returns three rows, with two rows for ID#1 */
    SELECT * FROM #dupes 

/* CTE to give each row that shares an ID a unique number */
    ;WITH toDelete AS
      (
        SELECT ID, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DWCreated) AS RN
        FROM #dupes 
      )

  /* Delete any row that is not the first instance of an ID */
    DELETE FROM toDelete WHERE RN > 1

/* Check the results: ID is now unique */
    SELECT * FROM #dupes

/* Clean up */
    DROP TABLE #dupes

Наличие столбца ORDER BY удобно, но не обязательно, если у вас нет предпочтения для какой из строк для удаления. Это также будет обрабатывать все экземпляры дубликатов записей, а не заставлять вас удалять одну строку за раз.

Ответ 7

Пробовал LIMIT 1? Это удалит только 1 из строк, соответствующих вашему запросу DELETE

DELETE FROM `table_name` WHERE `column_name`='value' LIMIT 1;

Ответ 8

Вы можете использовать max, что было важно в моем случае.

DELETE FROM [table] where id in 
(select max(id) from [table] group by id, col2, col3 having count(id) > 1)

Обязательно сначала проверяйте свои результаты и имеете предельное условие в своей "имеющей" клаузуле. С таким огромным запросом удаления вы можете сначала обновить свою базу данных.

Ответ 9

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

INSERT
'ID1219243408800307444663', '2004-01-20 10:20:55', 'INFORMATION', 'admin' (...)
INTO some_table;

Я тестировал инструкцию insert, так что теперь у меня были триплеты. Наконец, я запустил простой DELETE, чтобы удалить все из них...

DELETE FROM some_table WHERE logid = 'ID1219243408800307444663';

а затем INSERT еще раз, оставив меня с одной строкой и яркими возможностями первичного ключа.

Ответ 10

если вы можете добавить столбец, например

  ALTER TABLE yourtable ADD IDCOLUMN bigint NOT NULL IDENTITY (1, 1)

сделайте это.

затем подсчитайте группировку строк по столбцу проблемы, где count > 1, это будет идентифицировать ваши близнецы (или триплеты или что-то еще).

затем выберите столбец проблем, где его содержимое равно идентифицированному содержимому выше и проверьте идентификаторы в IDCOLUMN.

удалить из таблицы, где IDCOLUMN равно одному из этих идентификаторов.

Ответ 11

Это работает для PostgreSQL

DELETE FROM tablename WHERE id = 123 AND ctid IN (SELECT ctid FROM tablename WHERE id = 123 LIMIT 1)

Ответ 12

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

Ответ 13

В PostgreSQL имеется неявный столбец с именем ctid. См. wiki. Таким образом, вы можете использовать следующее:

WITH cte1 as(
    SELECT unique_column, max( ctid ) as max_ctid
    FROM table_1
    GROUP BY unique_column
    HAVING count(*) > 1
), cte2 as(
    SELECT t.ctid as target_ctid
    FROM table_1 t
    JOIN cte1 USING( unique_column )
    WHERE t.ctid != max_ctid
)
DELETE FROM table_1
WHERE ctid IN( SELECT target_ctid FROM cte2 )

Я не уверен, насколько безопасно использовать это, когда есть возможность одновременных обновлений. Поэтому может быть разумно сделать LOCK TABLE table_1 IN ACCESS EXCLUSIVE MODE;, прежде чем делать очистку.

Ответ 14

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

---  col1 , col2 ... coln are the table columns that are relevant. 
--- if not sure add all columns of the table in the select bellow and the where clause later. 

--- make a copy of the table T to be sure you can rollback anytime , if possible
--- check the @@rowcount to be sure it what you want
--- use transactions and rollback in case there is an error 

--- first find all with duplicate rows that are identical , this statement could be joined 
--- with the first one if you choose all columns 

select col1,col2, --- other columns as needed
  count(*) c into temp_duplicate group by col1,col2 having count(*) > 1 

--- save all the rows that are identical only once ( DISTINCT ) 

insert distinct * into temp_insert from T , temp_duplicate D where
T.col1 = D.col1 and
T.col2 = D.col2 --- and other columns if needed

--- delete all the rows that are duplicate

delete T from T , temp_duplicate D where 
T.col1 = D.col1 and
T.col2 = D.col2 ---- and other columns if needed

--- add the duplicate rows , now only once
insert into T select * from temp_insert 

--- drop the temp tables after you check all is ok