Нужно найти и перечислить дубликаты между несколькими CTE - PullRequest
0 голосов
/ 27 марта 2019

Мне нужно идентифицировать дубликаты в одной таблице, где пользователи неправильно ввели имя (например, вместо ввода «Джон» в fname и «Смит» в lname, запись, которая уже существует, они помещают » Смит "в fname и" Джон "в lname). Мне нужно идентифицировать эти дубликаты и перечислить дубликаты и их правильные записи.

Я установил два CTE, один для извлечения только тех столбцов, которые мне нужны, а другой - для тех же столбцов, которые содержат неверную информацию для удаления. Первичный запрос извлекает все столбцы и сравнивает полную таблицу с таблицей CTE с дубликатами. Я не могу сделать сравнение между двумя CTE, потому что произойдет ошибка (более одной строки, возвращенной подзапросом, используемым в качестве выражения). В его текущей форме запрос возвращает 9813408908970990872314 результатов (я отказался при экспорте 650k). Это база данных PostgreSQL, неизвестная версия, но я верю, что это 9+. В таблице person есть ~ 320 тыс. Допустимых строк и 2499 из wrong_order CTE. Ключевое поле - person.number, но у каждого будет уникальный номер, даже неправильные записи (каждая строка получает одну, но не у всех строк есть одна из-за удаленных записей, которые конфликтуют с правилами хранения данных).

WITH
  correct_order AS (
    SELECT (p.lname||', '|| p.fname) AS "name",
    p.number AS "num",
    p.birthdate AS "dob"
    FROM person p
    WHERE p.lname IS NOT NULL
    ),
  wrong_order AS (
    SELECT (p.fname||', '|| p.lname) AS "name",
    p.number AS "num",
    p.birthdate AS "dob"
    FROM person p
    WHERE (p.lname||', '|| p.fname) IN (p.fname||', '|| p.lname)
    )
SELECT
  correct_order.name AS "Correct Name",
  correct_order.num AS "Correct Num",
  correct_order.birthdate AS "Correct DOB",
  wrong_order.name AS "Wrong Name",
  wrong_order.num AS "Wrong Num",
  wrong_order.birthdate AS "Wrong DOB"
FROM
  correct_order, wrong_order
WHERE
  correct_order.name IN (SELECT wrong_order.name FROM wrong_order)

Я ожидал увидеть name / number / dob от обоих CTE, где оба набора данных совпадают между ними. Вместо этого я получил дублирование, в котором каждая мыслимая комбинация этих шести значений. Я пытался использовать объединение в основном запросе (correct_order JOIN wrong_order ON correct_order.name = wrong_order.name), но вы не можете использовать = для строки, а использование IN создает «более одной строки ...». Хотя, возможно, это возможно сделать в powershell, но я недостаточно силен, чтобы поднять это без посторонней помощи.

1 Ответ

1 голос
/ 27 марта 2019

У вас есть непреднамеренное перекрестное объединение (у FROM correct_order, wrong_order нет условия объединения).Это объясняет количество астрономических рядов.

Вам нужно выполнить запрос в следующем формате:

SELECTS /* columns you need */
FROM person AS correct
   JOIN person AS wrong
      ON (correct.fname, correct.lname) =
         (wrong.lname, wrong.fname)
WHERE correct.lname IS NOT NULL;

Надеюсь, я правильно понял ваше намерение.

Нет проблем при сравнении строкс =, это должно быть недоразумение.

...