如何根据SQL/PHP中的列值找到类似的行

如何根据SQL/PHP中的列值找到类似的行,php,mysql,sql,Php,Mysql,Sql,我正在建立一个电子商务pc商店,并已将所有产品及其规格存储为列(因此RAM、处理器、颜色、品牌等都是不同的列) 我建立了一个搜索来查找产品,并将其链接到一个页面,人们可以在该页面上查看产品及其所有信息 当有人查看一个产品时,我想要一个“类似产品”的部分它应该根据不同列的值获取这些产品,并获得最佳匹配 例如,假设我在这里有产品表: +----+------+--------+-------+--------+--------+ | id | Name | Type | Brand | Col

我正在建立一个电子商务pc商店,并已将所有产品及其规格存储为列(因此RAM、处理器、颜色、品牌等都是不同的列)
我建立了一个搜索来查找产品,并将其链接到一个页面,人们可以在该页面上查看产品及其所有信息

当有人查看一个产品时,我想要一个“类似产品”的部分
它应该根据不同列的值获取这些产品,并获得最佳匹配

例如,假设我在这里有产品表:

+----+------+--------+-------+--------+--------+
| id | Name |  Type  | Brand | Colour | Memory |
+----+------+--------+-------+--------+--------+
| 1  | Name1| laptop |  Asus | White  |  2GB   |
| 2  | Name2| laptop |  Acer |  Red   |  4GB   | 
| 3  | Name3|computer|   Hp  |  Blue  |  3GB   | 
| 4  | Name4| laptop |  Acer |  White |  6GB   | 
| 5  | Name5| laptop |   HP  |  Red   |  4GB   | 
+----+------+--------+-------+--------+--------+
假设用户正在查看产品id 1 那么,按照顺序,最好的匹配是:

+----+------+--------+-------+--------+--------+
| id | Name |  Type  | Brand | Colour | Memory |
+----+------+--------+-------+--------+--------+
| 4  | Name4| laptop |  Acer | White  |  6GB   |
| 2  | Name2| laptop |  Acer |  Red   |  4GB   | 
| 5  | Name5| laptop |   Hp  |  Red   |  4GB   | 
| 3  | Name3|computer|   HP  |  Blue  |  3GB   | 
+----+------+--------+-------+--------+--------+
| id |  Name |     Type | Brand | Colour | Memory | commonality |
|----|-------|----------|-------|--------|--------|-------------|
|  4 | Name4 |   laptop |  Acer |  White |    6GB |           2 |
|  2 | Name2 |   laptop |  Acer |    Red |    4GB |           1 |
|  5 | Name5 |   laptop |    HP |    Red |    4GB |           1 |
|  3 | Name3 | computer |    Hp |   Blue |    3GB |           0 |

所以我想,简而言之,我要问的是,我如何选择所有匹配列最多的行,按照它与当前行有多少匹配列的顺序,您可以比较感兴趣的项和剩余项集之间相同列的数量,并按匹配数的总和排序

如果要为某个属性赋予优先级,可以修改算法以包含权重。例如,布尔表达式
t1.Memory=t2.Memory
的值为1或0,可以更改为使用内存中差值的绝对值,以获得最接近的匹配。等等

请注意,此查询使用固定属性并假设没有空值-如果可能存在空值,则需要处理它(例如使用coalesce),并且还可以使用动态sql来说明要比较的不同数量的属性

此外,并非所有数据库都可以计算布尔表达式,如
t1.Memory=t2.Memory
(MySQL可以),它实际上是
case的缩写形式,当t1.Memory=t2.Memory然后1 else 0 end

select 
    t1.*
    , sum(t1.type = t2.type) 
    + sum(t1.Brand = t2.Brand) 
    + sum(t1.Colour = t2.Colour)  
    + sum(t1.Memory = t2.Memory) as commonality
from products  t1, products  t2 
where t2.id = 1 and t1.id <> t2.id
group by t1.id, t1.Name, t1.Type, t1.Brand, t1.Colour, t1.Memory
order by 
  sum(t1.type = t2.type) 
  + sum(t1.Brand = t2.Brand) 
  + sum(t1.Colour = t2.Colour) 
  + sum(t1.Memory = t2.Memory) desc, Brand

productid 1
与此表的关系究竟如何,除了id=1显然意味着您不希望结果中出现“id=1”?不,我不希望,因为他们正在查看产品id 1,根据您获取
类似产品的要求,在类似产品部分显示产品id 1是没有意义的,不应该在数据库中比较列。您应该使用相似性分数(根据要求为每列分配序数值,并将整行视为一个集合)或基于距离的度量(例如曼哈顿距离)来确定相似的组。好答案。。。还值得注意的是,您可以使用一个因子乘以每个求和值,为特定匹配类型分配权重。比如,如果您将类型匹配的值定为其他因素的两倍,那么您就可以做
sum(t1.Type=t2.Type)*2
@Orangepill实际上,包含权重(甚至让用户确定优先级顺序)会很简单