Найти различия между строками с дубликатами в одном поле - PullRequest
0 голосов
/ 21 февраля 2011

Я собираюсь удалить дубликаты из моей базы данных, используя

delete from table 
  where id not in (
    select min(id) 
      from table 
      group by foreign_key);

Однако я хотел бы сделать это при следующих условиях:

  • , если любая из повторяющихся строк имеет значение в fieldA или fieldB
    • , если какой-либо из дубликатов имеет значение для fieldA или fieldB, но в каждом поле есть только одно уникальное значение, оставьте это значение
    • если в каждой строке более одного уникального значения, сообщите эту информацию вместе с id и foreign_key, чтобы это значение можно было исправить вручную.

По умолчанию fieldA и fieldB равны NULL, но в некоторых случаях в эти поля вводятся данные.

Вот некоторые примеры данных:

| id | foreign_key | fieldA | fieldB |
|----+-------------+--------+--------|
|  1 |           1 | NULL   | NULL   |
|  2 |           1 | A1     | B1     |
|  3 |           1 | NULL   | NULL   |
|  4 |           2 | A2     | B2     |
|  5 |           2 | A3     | B2     |
|  6 |           3 | NULL   | NULL   |
|  7 |           4 | A4     | B4     |
|  8 |           5 | A5     | NULL   |
|  9 |           5 | NULL   | B5     |
| 10 |           6 | A6     | B6     |
| 11 |           6 | A7     | B6     |
| 12 |           7 | NULL   | B7     |
| 13 |           7 | NULL   | B7     |

Я хочу сохранить:

| id | foreign_key | fieldA | fieldB |
|----+-------------+--------+--------|
|  2 |           1 | A1     | B1     |
|  4 |           2 | NULL   | B2     |
|  6 |           3 | NULL   | NULL   |
|  7 |           4 | A4     | B4     |
|  8 |           5 | A5     | B5     |
| 10 |           6 | NULL   | B6     |
| 12 |           7 | NULL   | B7     |

И я хотел бы, чтобы эта информация была возвращена:

foreign_key 2 has two distinct values of fieldA: A2 and A3

1 Ответ

1 голос
/ 22 февраля 2011

Мне нужно выполнить прямо сейчас, но вот запрос для начала:

SELECT id, foreign_key, 
    group_concat(DISTINCT fieldA) as A, count(DISTINCT fieldA) as `#A`,
    group_concat(DISTINCT fieldB) as B, count(DISTINCT fieldB) as `#B`
  FROM t1
  GROUP BY foreign_key
;

На тестовых данных это возвращает:

| id | foreign_key | A     | #A | B    | #B |
+----+-------------+-------+----+------+----+
|  1 |           1 | A1    |  1 | B1   |  1 |
|  4 |           2 | A2,A3 |  2 | B2   |  1 |
|  6 |           3 | NULL  |  0 | NULL |  0 |
|  7 |           4 | A4    |  1 | B4   |  1 |
|  8 |           5 | A5    |  1 | B5   |  1 |
| 10 |           6 | A6,A7 |  2 | B6   |  1 |
| 12 |           7 | NULL  |  0 | B7   |  1 |

Запрос на сохранение строк:

SELECT id, foreign_key, 
    group_concat(DISTINCT fieldA) as A, count(DISTINCT fieldA) as `#A`, 
    group_concat(DISTINCT fieldB) as B, count(DISTINCT fieldB) as `#B`
  FROM t1
  GROUP BY foreign_key
  HAVING `#A` < 2 AND `#B` < 2
;

Запрос на строки, требующие вмешательства оператора:

SELECT id, foreign_key, 
    group_concat(DISTINCT fieldA) as A, count(DISTINCT fieldA) as `#A`, 
    group_concat(DISTINCT fieldB) as B, count(DISTINCT fieldB) as `#B`
  FROM t1
  GROUP BY foreign_key
  HAVING `#A` >= 2 OR `#B` >= 2
;

GROUP_CONCAT может не подходить, в зависимости от формата сохраняемых данныхв столбцах.Однако в сочетании с #A и #B вы можете определить, когда это не подходит, поэтому это не должно быть большой проблемой.Это также может оказать слишком большое влияние на производительность, но я не могу представить другую агрегатную функцию, которая могла бы использоваться таким же образом (GROUP_COALESCE было бы неплохо).

...