Я разрабатываю веб-приложение для витрин. Когда потенциальный клиент просматривает продукт на веб-сайте, я хотел бы предложить набор подобных продуктов из базы данных автоматически (vs требует, чтобы человек явно вводил данные/сопоставления данных о продуктах).Веб-сайт торговой марки ECommerce: Поиск похожих продуктов Программно
Фактически, когда вы думаете об этом, большинство баз данных магазинов уже имеют множество доступных данных о подобии. В моем случае Products
может быть:
- отображается на
Manufacturer
(акаBrand
) - отображается на один или более
Categories
и - отображается на один или более
Tags
(акаKeywords
).
Путем подсчета количества общих атрибутов между продуктом и всех остальных, можно вычислить «SimilarityScore» для сравнения других продуктов против одного просматриваемого заказчиком. Вот моя первая реализация прототипа:
;WITH ProductsRelatedByTags (ProductId, NumberOfRelations)
AS
(
SELECT t2.ProductId, COUNT(t2.TagId)
FROM ProductTagMappings AS t1 INNER JOIN
ProductTagMappings AS t2 ON t1.TagId = t2.TagId AND t2.ProductId != t1.ProductId
WHERE t1.ProductId = '22D6059C-D981-4A97-8F7B-A25A0138B3F4'
GROUP BY t2.ProductId
), ProductsRelatedByCategories (ProductId, NumberOfRelations)
AS
(
SELECT t2.ProductId, COUNT(t2.CategoryId)
FROM ProductCategoryMappings AS t1 INNER JOIN
ProductCategoryMappings AS t2 ON t1.CategoryId = t2.CategoryId AND t2.ProductId != t1.ProductId
WHERE t1.ProductId = '22D6059C-D981-4A97-8F7B-A25A0138B3F4'
GROUP BY t2.ProductId
)
SELECT prbt.ProductId AS ProductId
,IsNull(prbt.NumberOfRelations, 0) AS TagsInCommon
,IsNull(prbc.NumberOfRelations, 0) AS CategoriesInCommon
,CASE WHEN SimilarProduct.ManufacturerId = SourceProduct.ManufacturerId THEN 1 ELSE 0 END as SameManufacturer
,CASE WHEN SimilarProduct.ManufacturerId = SourceProduct.ManufacturerId
THEN IsNull(prbt.NumberOfRelations, 0) + IsNull(prbc.NumberOfRelations, 0) + 1
ELSE IsNull(prbt.NumberOfRelations, 0) + IsNull(prbc.NumberOfRelations, 0)
END as SimilarityScore
FROM Products AS SourceProduct,
Products AS SimilarProduct INNER JOIN
ProductsRelatedByTags prbt ON prbt.ProductId = SimilarProduct.Id FULL OUTER JOIN
ProductsRelatedByCategories prbc ON prbt.ProductId = prbc.ProductId
WHERE SourceProduct.Id = '22D6059C-D981-4A97-8F7B-A25A0138B3F4'
который приводит данные, как это:
ProductId TagsInCommon CategoriesInCommon SameManufacturer SimilarityScore
------------------------------------ ------------ ------------------ ---------------- ---------------
6416C19D-BA4F-4AE6-AB75-A25A0138B3A5 1 0 0 1
77B2ECC0-E2EB-4C1B-A1E1-A25A0138BA19 1 0 0 1
2D83276E-40CC-44D0-9DDF-A25A0138BE14 2 1 1 4
E036BFE0-BBB5-450C-858C-A25A0138C21C 3 0 0 3
Я не гуру производительности SQL, поэтому у меня есть следующие вопросы для вас SQL гуру:
- Являются ли common-table-expression s (CTE) подходящими/оптимальными в этом прецеденте? (Они, похоже, облегчают чтение/выполнение SQL). Есть ли способ сохранить соединение там где-нибудь с учетом представленной выше модели?
и
- ли это быть хорошим кандидатом для индексированного представления (для упорства) или же это добавить чрезмерные затраты на изменения исходных данных? В этом случае я сделаю это хранимой процедурой, которая обновит физическую таблицу
SimilarProductMappings
для любого данного продукта.
Я не думаю, что вы можете использовать CTE в индексированном виде, как это. – RBarryYoung
@BenSwayne. , , Сырое количество общих атрибутов - очень рудиментарная мера сходства. Вы обнаружите, что продукты, которые имеют много атрибутов, будут всплывать в верхней части списка для многих других продуктов. –
@GordonLinoff - Вы правы, этот вопрос был больше о компоненте SQL моей задачи, чем до точности моего алгоритма подобия. Я предполагаю, что в игру приходят больше факторов и, возможно, также возможность добавлять весовые коэффициенты к каждому из факторов при объединении общей оценки сходства.В конце концов это несколько специфично для конкретного случая, и его необходимо будет настроить для некоторых приложений клиентов. Но это должно обеспечить хорошую «из коробки» откат реализации для 80% клиентов, которым не нужно многого. – BenSwayne