4

好的,我有一个存储两个键的关系,一个产品 ID 和一个属性 ID。我想找出与给定产品最相似的产品。(属性实际上是数字,但它使示例更加混乱,因此已将它们更改为字母以简化视觉表示。)

Prod_att

Product | Attributes  
   1   |    A     
   1   |    B  
   1   |    C  
   2   |    A  
   2   |    B  
   2   |    D  
   3   |    A  
   3   |    E  
   4   |    A  

最初这似乎相当简单,只需选择产品具有的属性,然后计算每个产品共享的属性数量。然后将此结果与产品具有的属性数量进行比较,我可以看到两种产品的相似程度。这适用于相对于其比较产品具有大量属性的产品,但是当产品的属性非常少时会出现问题。例如,产品 3 几乎与其他所有产品都有一个平局(因为 A 很常见)。

SELECT Product, count(Attributes)  
FROM Prod_att  
WHERE Attributes IN  
(SELECT Attributes  
FROM prod_att  
WHERE Product = 1)  
GROUP BY Product
;  

有关如何解决此问题或改进我当前查询的任何建议?
谢谢!

*编辑:产品 4 将为所有产品返回 count() =1。我想展示产品 3 更相似,因为它具有更少的不同属性。

4

3 回答 3

2

尝试这个

SELECT 
  a_product_id, 
  COALESCE( b_product_id, 'no_matchs_found' ) AS closest_product_match
FROM (
  SELECT 
    *,  
    @row_num := IF(@prev_value=A_product_id,@row_num+1,1) AS row_num,
    @prev_value := a_product_id
  FROM 
    (SELECT @prev_value := 0) r
    JOIN (
        SELECT 
         a.product_id as a_product_id,
         b.product_id as b_product_id,
         count( distinct b.Attributes ),
         count( distinct b2.Attributes ) as total_products
        FROM
          products a
          LEFT JOIN products b ON ( a.Attributes = b.Attributes AND a.product_id <> b.product_id )
          LEFT JOIN products b2 ON ( b2.product_id = b.product_id )
       /*WHERE */
         /*  a.product_id = 3 */
        GROUP BY
         a.product_id,
         b.product_id
        ORDER BY 
          1, 3 desc, 4
  ) t
) t2 
WHERE 
  row_num = 1

以上query获取closest matches所有产品的,您可以product_id在最里面的查询中包含,以获取特定的结果product_id,我使用过LEFT JOIN这样即使 aproduct没有匹配项,它也会显示

SQLFIDDLE

希望这可以帮助

于 2013-05-08T18:38:25.100 回答
0

您可以编写一个小视图,为您提供两个产品之间的全部共享属性。

create view vw_shared_attributes as
select a.product, 
      b.product 'product_match', 
      count(*) 'shared_attributes'
from  your_table a
  inner join test b on b.attribute = a.attribute and b.product <> a.product
group by a.product, b.product  

然后使用该视图选择最佳匹配项。

   select product,
      (select top 1 s.product_match from vw_shared_attributes s where t.product = s.product order by s.shared_attributes desc)
    from your_table t
    group by product

有关示例,请参见http://www.sqlfiddle.com/#!6/53039/1

于 2013-05-08T17:35:02.603 回答
0

尝试“伯努利参数的威尔逊分数置信区间的下限”。当 n 较小时,这会明确处理统计置信度问题。它看起来像很多数学,但实际上这是正确地做这类事情所需的最少数学量。该网站很好地解释了它。

这假设可以从正面/负面评分迈向匹配/不匹配属性的问题。

以下是正面和负面评分和 95% CL 的示例:

SELECT widget_id, ((positive + 1.9208) / (positive + negative) - 
1.96 * SQRT((positive * negative) / (positive + negative) + 0.9604) / 
(positive + negative)) / (1 + 3.8416 / (positive + negative)) 
AS ci_lower_bound FROM widgets WHERE positive + negative > 0 
ORDER BY ci_lower_bound DESC;
于 2013-05-08T17:24:43.367 回答