Для моего приложения, используя Postgres ...
Проблема
Каждый пользователь должен быть связан с N-числом случаев, определяя одно- отношение ко многим, но из-за неправильной логики приложения c пользователи обычно дублируются в БД, что приводит к нескольким идентификаторам для каждого конкретного человека.
Учитывая, что эти типы почти дублируют большинство пользователей, это привело к тому, что каждый пользователь будет почти всегда представлен Y-числом идентификаторов в таблице users
.
В этом контексте почти дубликат означает две строки, которые в основном похожи. Вот пример почти дубликата.
| id | first_name | last_name | str_adrr |
------------------------------------------------
| 1 | Mary | Doe | 124 Main Ave |
| 2 | Mary | Doe | 124 Main St |
Цель состоит в том, чтобы удалить почти всех дубликатов пользователей, кроме одного, оставив одного пользователя, при этом все соответствующие дела будут связаны с этим единственным пользователем. Завершение отношения один-ко-многим между пользователями и делами.
Мой подход
Первый шаг
Я нечетко сопоставил пользователей и сгруппировал их по cluster_id в качестве идентификатора , Где cluster_id используется для указания самой группировки; все строки с cluster_id 1
считаются дубликатами друг друга.
Вот пример users
таблицы
| id | first_name | last_name | str_adrr | group | cluster_id
-------------------------------------------------------------------------------------
| 1 | Mary | Doe | 124 Main Ave | Mary Doe 124 Main Ave | 1
| 2 | Mary | Doe | 124 Main St | Mary Doe 124 Main Ave | 1
| 7 | Mary | Doe | 124 Main Ave | Mary Doe 124 Main Ave | 1
| 4 | Mary | Does | 124 Main Ave | Mary Doe 124 Main Ave | 1
| 5 | James | Smith | 14 Street NW |James Smith 14 Street NW | 2
| 6 | James | Smith | 14 Street NW |James Smith 14 Street NW | 2
| 10 | James | Smth | 14 Street NW |James Smith 14 Street NW | 2
| 11 | Paula | James | 21 River SW | Paula James21 River SW | 3
| 45 | Paula | James | 21 River SW | Paula James21 River SW | 3
Для другой таблицы с именем cases
. Вот пример соответствующих столбцов из этой таблицы:
| id | user_id
---------------
| 1 | 1 # corresponds to mary
| 2 | 2 # corresponds to mary
| 3 | 4 # corresponds to mary
| 4 | 7 # corresponds to mary
| 5 | 10 # corresponds to james
| 6 | 11 # corresponds to paula
| 7 | 45 # corresponds to paula
| 8 | 1 # corresponds to mary
| 9 | 10 # corresponds to james
| 10 | 10 # corresponds to james
| 11 | 6 # corresponds to james
user_id
в этой таблице cases
соответствует id
из таблицы users
Пользовательский идентификатор может есть много (до нескольких тысяч) дел.
Шаг 2
Я присоединился к таблицам users
и cases
Вот пример таблицы результатов , users_cases
:
|cluster_id| user_id| case_id
----------------------------------
| 1 | 1 | 1
| 1 | 1 | 8
| 1 | 2 | 2
| 1 | 4 | 3
| 1 | 7 | 4
| 2 | 10 | 5
| 2 | 10 | 9
| 2 | 10 | 10
| 2 | 6 | 11
| 3 | 11 | 6
| 3 | 11 | 7
Шаг 3
Мне нужно было определить, какой user_id
в данной группе cluster_id
связан с наибольшим количеством случаев из user_cases
Таблица.
Я смог сделать это и в итоге получил таблицу max_cluster_user
со следующей формой
|cluster_id| user_id| case_id_count
-------------------------------------
| 1 | 1 | 2
| 2 | 10 | 3
| 3 | 11 | 1
для перевода. Первая строка указывает, что для cluster_id
со значением 1
, user_id
с наибольшим числом случаев составляет 2
, а количество случаев представлено case_id_count
, которое имеет значение 2
.
Шаг 4: Где мне нужна помощь
Затем мне нужно обновить таблицу user_cases
(или создать новую таблицу такой же формы), чтобы каждый user_id
был одинаковым для каждая строка в группе cluster_id
. Результат должен выглядеть примерно так:
|cluster_id| user_id| case_id
----------------------------------
| 1 | 1 | 1
| 1 | 1 | 8
| 1 | 1 | 2
| 1 | 1 | 3
| 1 | 1 | 4
| 2 | 10 | 5
| 2 | 10 | 9
| 2 | 10 | 10
| 2 | 10 | 11
| 3 | 11 | 6
| 3 | 11 | 7
Я не знаю, как этого добиться. Ограничение заключается в том, что это должно быть сделано с помощью Postgresql совместимого SQL.
решения процедурного кода для шага 4
Я набросал это как код, чтобы обдумать это процедурно, это может помочь. Хотя я знаю, что это не жизнеспособное решение, так как при> 500 тыс. Записей для этого типа логи c потребуется несколько дней, чтобы работать как есть.
# max_cluster_user refers to the table of the same name
for cluster in max_cluster_user:
# get the users within a specific cluster
cluster_users = [user for user in users if user['cluster_id'] == cluster['cluster_id']]
# users refers to the table of the same name
for user in cluster_users:
# get the cases associated with the given id
user_cases = [case for case in cases if case['user_id'] == user['id']
for user_case in user_cases:
# update the user_id for a case
user_case['user_id = cluster['user_id']
Заранее спасибо