Как я могу удалить пары совпадающих строк?

У меня есть таблица, содержащая данные заказа на продажу (номер заказа, номер продукта, цена продажи и т.д.).

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

Я хочу удалить все строки с отрицательной суммой вместе с соответствующей им строкой (или любой другой с такой же суммой) с положительной суммой.

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

Как удалить все строки с отрицательной суммой, а также одну строку для каждой с обратной суммой?


person Ben S    schedule 12.11.2009    source источник


Ответы (4)


в зависимости от того, сколько данных есть, я бы просто сделал это методом грубой силы.

выберите все отрицательные итоговые строки во временную таблицу

используйте курсор для просмотра каждой строки, затем запросите в базе данных одно совпадение (используя, возможно, max() для временной метки, номера заказа или любого другого первичного ключа, который у вас может быть. Удалите эту одну «соответствующую» строку.

затем удалите все отрицательные строки

Без сомнения, вы можете использовать подзапрос и сделать это в одном операторе, но к тому времени, когда я это понял и протестировал, я бы выполнил работу, используя вышеизложенное :)

person MikeW    schedule 12.11.2009

Задачи очистки данных болезненны, несмотря ни на что. Из того, что вы описали, недостаточно информации для полной автоматизации этой задачи. Это типично для очистки данных.

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

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

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

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

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

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

Другой совет заключается в том, что SQL Anywhere имеет многотабличный синтаксис DELETE. Я не использую SQL Anywhere, но я нашел это в онлайн-документах:

Syntax

DELETE [ row-limitation ] 
  [ FROM ] [ owner.]table-expression
  [ FROM table-list [,...] ]
  [ WHERE search-condition ]
  [ ORDER BY { expression | integer } [ ASC | DESC ], ... ]
  [ OPTION( query-hint, ... ) ]

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

person Bill Karwin    schedule 12.11.2009

Что такое общий идентификатор, который связывает 2 строки? Без этого вы не можете, потому что вам нечем связать строки

Во всяком случае, это было бы что-то вроде

DELETE MyTable
WHERE EXISTS (
    SELECT * FROM MyTable M2
    GROUP BY M2.LinkID
    HAVING SUM(M2.ValueCol) < 0 AND MyTable.KeyCol = M2.KeyCol
    )
person gbn    schedule 12.11.2009

Я бы запустил внутренний SELECT без переноса DELETE один раз, чтобы убедиться, что данные выглядят нормально, перед выполнением, но я почти уверен, что все будет в порядке.

DELETE FROM
   orders
WHERE
   orderID IN (
       SELECT
          orderID
       FROM (
          SELECT 
             MIN(orderID) orderID, total
          FROM
             orders
          WHERE
             total IN (
                SELECT
                   total * -1
                FROM
                   orders
                WHERE
                   total < 0
             )
          GROUP BY
             total
      )derived
   )

DELETE FROM
    orders
WHERE
    total < 0
person David Hedlund    schedule 12.11.2009