Я начну с составления более формального определения таблиц:
warehouse:
warehouse_id,
warehouse_product_id,
product_brand,
product_name,
local_id
Здесь я бы использовал local_id в качестве внешнего ключа к вашей таблице «Модель», но чтобы избежать дальнейшей путаницы,Я назову это 'local'
local:
id,
product_brand,
product_name
Кажется, что таблица, которую вы описываете как 'product', является избыточной.
Очевидно, что до перекрестной ссылки на данные local_id будет нулевым.Но после того, как он будет заполнен, его не нужно будет менять, и, учитывая warehouse_id, группу и продукт, вы можете легко найти свой локальный дескриптор:
SELECT local.*
FROM local, warehouse
WHERE local.id=warehouse.local_id
AND warehouse.product_brand=local.product_brand
AND warehouse_id=_____
AND warehouse.product_brand=____
AND warehouse.product_name=____
Так что все, что вам нужно сделать, это заполнитьссылки.Soundex - довольно грубый инструмент - лучшим решением для этого был бы алгоритм расстояния Левенштейна .Здесь есть реализация mysql
Учитывая набор строк в таблице хранилища, которые необходимо заполнить:
SELECT w.*
FROM warehouse w
WHERE w.local_id IS NULL;
... для каждой строки определить лучшийсопоставить как (используя значения из предыдущего запроса как w. *) ....
SELECT local.id
FROM local
WHERE local.product_brand=w.product_brand
ORDER BY levenstein(local.product_name, w.product_name) ASC
LIMIT 0,1
Но это найдет наилучшее совпадение, даже если 2 строки совершенно разные!Следовательно ....
SELECT local.id
FROM local
WHERE local.product_brand=w.product_brand
AND levenstein(local.product_name, w.product_name)<
(IF LENGTH(local.product_name)<LENGTH(w.product_name),
LENGTH(local.product_name), LENGTH(w.product_name))/2
ORDER BY levenstein(local.product_name, w.product_name) ASC
LIMIT 0,1
... требуется как минимум половина строки для сопоставления.
Таким образом, это можно реализовать в одном операторе обновления:
UPDATE warehouse w
SET local_id=(
SELECT local.id
FROM local
WHERE local.product_brand=w.product_brand
AND levenstein(local.product_name, w.product_name)<
(IF LENGTH(local.product_name)<LENGTH(w.product_name),
LENGTH(local.product_name), LENGTH(w.product_name))/2
ORDER BY levenstein(local.product_name, w.product_name) ASC
LIMIT 0,1
)
WHERE local_id IS NULL;