PHP - MySQL搜索数据库表返回结果与百分比匹配

时间:2011-10-29 19:44:22

标签: php mysql count subquery match

在我的网站上,我允许用户选择他们喜欢或感兴趣的内容。这是使用预定义的下拉菜单完成的,因此每次用户登录网站时,他们都会获得拥有和他们一样兴趣。

这是通过使用MySQL WHERE子句获取登录用户的兴趣(存储在db中)并与站点上的其他用户匹配来完成的。但我遇到的问题是如何显示每个用户旁边的百分比或分数,以显示他们与登录用户兴趣的匹配程度。

例如:

  • user1 - 与您的兴趣匹配<60%
  • user1 - 与您的兴趣匹配<30%
  • user2 - 与您的兴趣匹配<20%

如果所有用户都匹配,则每个用户都有5种不同的兴趣。

表结构示例:

CREATE TABLE IF NOT EXISTS `helloworld` (
  `id` int(9) NOT NULL AUTO_INCREMENT,
  `like1` varchar(300) NOT NULL,
  `like2` varchar(300) NOT NULL,
  `like3` varchar(300) NOT NULL,
  `name` varchar(300) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

示例查询:

SELECT * FROM helloworld WHERE like1='football' AND like2='art'

我在考虑使用COUNT功能,但我不确定?或者我应该使用子查询?

编辑:我使用PHP作为服务器端语言。用户不能键入自己的喜欢,必须使用预定义的列表。

5 个答案:

答案 0 :(得分:0)

你和用户之间有很多关系。您的表违反了1NF - 您有like列的“重复组”。相反,有一个单独的关联表来处理这个:

create table user_likes (
    user_id int(9) NOT NULL,
    like_name varchar(300) NOT NULL
);

现在你可以使用更简单的查询来获得匹配的数量 - 我会留给你研究:)

提示:您可以使用位掩码来帮助确定匹配,为每个不同的like_name分配预定义的2位数幂(help是一个like_names表)。

答案 1 :(得分:0)

首先,我认为你需要一个不同的架构。你拥有的那个将使你的任务非常困难,因为它不够灵活。我推荐这样的东西:

CREATE TABLE `users` (
    `id`        INT NOT NULL AUTO_INCREMENT,
    `name`      VARCHAR(300) NOT NULL,
    PRIMARY KEY (`id`)
);

CREATE TABLE `likes` (
    `user`      INT NOT NULL,
    `interest`  VARCHAR NOT NULL,
    PRIMARY KEY (`user`,`interest`)
);

(对不起,我不记得如何在MySQL中设置FK关系,但我相信你可以很容易地解决这个问题。)

然后,确定每个用户的“喜欢”数量:

SELECT COUNT(*)
FROM users
JOIN likes ON likes.user=users.id
WHERE users.name = 'bob';

然后确定两个用户有多少共同点:

SELECT COUNT(*)
FROM users AS u1
JOIN likes AS l1 ON (l1.user = u1.id)
JOIN likes AS l2 ON (l1.interest = l2.interest)
JOIN users AS u2 ON (l2.user = u2.id)
WHERE u1.name = 'bob'
    AND u2.name = 'alice';

然后根据这三个数字,您可以根据需要计算百分比 - 可能在您的客户端代码中,但如果需要,您可以使用子选择在所有SQL端执行。

示例:

USERS:
 id | name
----+-------
  1 | bob
  2 | alice

LIKES:
 user | interest
------+----------
    1 | fish
    1 | baseball
    2 | fish
    2 | cooking
    2 | baseball

运行bobalice的第一个查询将显示bob具有 2 兴趣,并且Alice具有 3 兴趣。然后运行第二个查询将显示他们的bob和alice一起拥有 2 共享兴趣。

然后你可以向鲍勃展示爱丽丝分享他100%的兴趣(2/2 = 100%),你可以向爱丽丝展示鲍勃共享66%(2/3 = 66%)的兴趣。

答案 2 :(得分:0)

你最好在PHP级别检查一下。考虑到每个用户的兴趣,您可以使用count()对array_intersect()的结果进行评分,以比较访问者和其他用户的兴趣(http://www.php.net/manual/en/function.array-intersect。 PHP)。如果你允许5个兴趣,那就是(5 * count(array_intersect({params})))%。不匹配,0%,4场比赛,80%。

答案 3 :(得分:0)

我是这样做的。假设$ like1,$ like2和$ like3是当前用户的值:

SELECT (IF(like1='$like1',1,0) + IF(like2='$like2',1,0) + IF(like3='$like3',1,0))/3*100 match_percent,
COUNT(id)
FROM helloworld
GROUP BY match_percent;

答案 4 :(得分:0)

这将使用您当前的架构:

select
    t2.id,
    t2.name
    sum(
        t1.like1 in (t2.like1, t2.like2, t2.like3, t2.like4, t2.like5) +
        t1.like2 in (t2.like1, t2.like2, t2.like3, t2.like4, t2.like5) +
        t1.like3 in (t2.like1, t2.like2, t2.like3, t2.like4, t2.like5) +
        t1.like4 in (t2.like1, t2.like2, t2.like3, t2.like4, t2.like5) +
        t1.like5 in (t2.like1, t2.like2, t2.like3, t2.like4, t2.like5)
    ) * 20 as percent_match
from helloworld t1
left join helloworld t2 on t1.id != t2.id
group by 1, 2
order by 3 desc;

这是有效的,因为mysql中的true1 - 总结真相将总计匹配数。