Postgresql: обновить несколько строк в одной таблице, учитывая массив идентификаторов из другой таблицы - PullRequest
0 голосов
/ 30 мая 2018

У меня есть две таблицы: одна содержит отдельных лиц, а другая таблица содержит названия мест.Каждый человек связан с идентификатором названия места - и идентификатор названия места дает больше информации о месте (например, название, долгота и широта).Таблица географических названий искажена, есть много полудубликатов (имена написаны немного по-другому, например, Лондон / Лондон).Для каждого названия места у меня теперь также есть «реальное» название места через Google API.

Персоны:

ID    Name     Birthplace
1     John     1
2     Sarah    2
3     Jane     3
4     Tom      4

Местные названия:

ID   PlaceName       GooglePlaceName
1    New York City   New York, NY, USA    
2    Amsterdam       Amsterdam, Netherlands
3    Londen          London, UK
4    London          London, UK

Так что, глядя на эти данные, Джейн и Том фактически находятся в одном месте.

У меня уже есть запрос, который получает повторяющиеся идентификаторы из таблицы названий мест:

SELECT id FROM placenames WHERE googleplacename IN (SELECT googleplacename FROM placenames GROUP BY googleplacename HAVING COUNT (googleplacename) > 1);

Это возвращает

    ID
1   3
2   4

Теперь мне интересно, возможно ли эточтобы обновить таблицу персон, чтобы Джейн и Том оба получили один и тот же идентификатор места рождения (неважно, 3 или 4) и впоследствии удалили дубликаты строк из таблицы названий мест, чтобы либо название места с идентификатором 3, либо название местас ID 4 остается, в зависимости от того, кто остался в таблице лиц.

Если я полностью иду в неправильном направлении, пытаясь решить эту проблему с помощью SQL, я также хотел бы знать.Я использую Java и Spring для доступа к базе данных.

1 Ответ

0 голосов
/ 30 мая 2018

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

т.е.

birthplace
3
4

становится

birthplace
3
3

для этого сначала создайте таблицу, отображающую значения оригинала и идентификатора замены

ваш оператор выбора имеет исходные идентификаторы, к которым вы можете добавить идентификаторы замены, используя оконную функцию first_value, разделенную на googleplacename

Используйте эту таблицу сопоставления в предложении from оператора update persons, объединяя записи, где birthplace равен original_id, но не replacement_id

UPDATE persons
SET birthplace = replacement_id

FROM (
  SELECT id original_id, FIRST_VALUE(id) OVER (PARTITION BY googleplacename) replacement_id
  FROM placenames 
  WHERE googleplacename IN (
    SELECT googleplacename FROM placenames GROUP BY 1 HAVING COUNT(*) > 1
  ) 
) replacement_table
WHERE birthplace = original_id
  AND birthplace != replacement_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...