我正在开发一个店面 Web 应用程序。当潜在客户在网站上查看产品时,我想自动从数据库中推荐一组相似的产品(而不是需要人工明确输入产品相似性数据/映射)。
事实上,仔细想想,大多数店面数据库已经有大量的相似性数据可用。在我的情况下Products
可能是:
- 映射到
Manufacturer
(akaBrand
), - 映射到一个或多个
Categories
,并且 - 映射到一个或多个
Tags
(又名Keywords
)。
通过计算产品与所有其他产品之间共享属性的数量,您可以计算“相似度得分”,以将其他产品与客户正在查看的产品进行比较。这是我最初的原型实现:
;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 专家:
- 在这个用例中,公共表表达式(CTE)是否合适/最佳?(他们确实似乎更容易阅读/遵循 SQL)。鉴于上述模型,有没有办法在任何地方保存连接?
和
- 这会是索引视图(用于持久性)的良好候选者,还是会增加源数据更改的过多成本?在这种情况下,我将使它成为一个存储过程,它可以更新
SimilarProductMappings
任何给定产品的物理表。