3

该图像显示了我的表的结构。第一行表示tutorB 给studentD 10 分。第二行表示tutorE还没有给studentD打分。

在此处输入图像描述

如何生成下表?我在 stackoverflow.com 中引用了另一篇文章。MySQL中的协同过滤?然而,我仍然很困惑。

在此处输入图像描述

从上图中,o表示推荐,大于等于7;x 表示不推荐,比率小于 7。

例如,tutorB 给 studentD 10 分,因此,从图片的第二行,我们可以看到 StudentD 列有一个“o”。(而其他三行的数据现在只是随机分配的。)

现在,如果我想为导师 A 推荐一个学生。导师 B、C 和 D 的等级(或相似度)分别为 0,2 和 3。

如何生成 SQL 以便能够将比率转换为“o”和“x”并计算排名。而且,最重要的是,我想从图片中向 TutorA 推荐 StudentH。

我应该如何修改上一篇文章中的代码?而且,如果我上面提到的想法正确?

谢谢。

==================================================== ===========================

已编辑

我在数据库中有以下数据。第一行表示 10 分是导师 A 给学生 C 的。

在此处输入图像描述

为了更好地理解,我将其转换为另一个表。v是速率的值。

在此处输入图像描述

create temporary table ub_rank as 
select similar.NameA,count(*) rank
from tbl_rating target 
join tbl_rating similar on target.NameB= similar.NameB and target.NameA != similar.NameA
where target.NameA = "tutorA"
group by similar.NameA;

select similar.NameB, sum(ub_rank.rank) total_rank
from ub_rank
join ub similar on ub_rank.NameA = similar.NameA 
left join ub target on target.NameA = "tutorA" and target.NameB = similar.NameB
where target.NameB is null
group by similar.NameB
order by total_rank desc;

select * from ub_rank;

上面的代码引用自Collaborative filtering in MySQL? . 我有几个问题。

  1. SQL中有2个部分。我可以从第一部分中选择 *。但是,如果我如上图输入整个SQL,系统提示Table 'mydatabase.ub' doesn't exist我应该如何修改代码?

  2. 代码将找到相似之处。我应该如何更改代码,如果标记小于 7,则更改为o,否则更改为v,并计算给定用户的相似度?

在此处输入图像描述

4

3 回答 3

1

无耻地借鉴上一个问题的答案看看这是否能解决问题:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(case when NameB = ''',
      NameB,
      ''' then (case when rate >= 7 then ''x'' else ''o'' end) else '' '' end) AS ',
      replace(NameB, ' ', '')
    )
  ) INTO @sql
from tbl_rating
where RoleA = 'Tutor';

SET @sql = CONCAT('SELECT NameA, ', @sql, 
' from tbl_rating
where RoleA = ''Tutor''
group by NameA');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

这是一个 SQL Fiddle

于 2013-03-25T01:35:57.483 回答
1

您的数据库架构实际上并不容易使用。

这是获取详尽评级表的查询:

SELECT Tutor.Name, Student.Name, 
  CASE WHEN Rating.Rate IS NULL THEN ''
    WHEN Rating.Rate > 6 THEN 'o'
    ELSE 'x' END
FROM (
    SELECT DISTINCT NameB AS Name
    FROM tbl_rating 
    WHERE RoleB='Tutor'
    UNION
    SELECT DISTINCT NameA AS Name
    FROM tbl_rating
    WHERE RoleA='Tutor'
    ORDER BY Name) AS Tutor
CROSS JOIN (
    SELECT DISTINCT NameB AS Name
    FROM tbl_rating 
    WHERE RoleB='Student'
    UNION
    SELECT DISTINCT NameA AS Name
    FROM tbl_rating
    WHERE RoleA='Student'
    ORDER BY Name) AS Student
LEFT JOIN tbl_rating AS Rating
ON Tutor.Name = Rating.NameA
AND Student.Name = Rating.NameB
ORDER BY Tutor.Name, Student.Name

上述查询的工作原理是从表中提取所有导师的列表(第一个子查询别名为Tutor)和所有学生的列表(第二个子查询Student),对两组进行乘积以获得导师和学生的所有可能组合。然后它与评分表进行外连接,该表关联查找学生对导师所做的所有评分,并填写NULL不存在的评分。(获得相反评价的查询——即导师对学生的评价——可以通过交换NameANameBLEFT JOIN子句中获得)。根据CASE要求将数字(或空)评级转换为符号。

为了相似之处,我们需要再添加两个连接:

  • 再来一张Tutor
  • 另一个在Rating

因此给出:

SELECT T1.Name AS Tutor1 , T2.Name AS Tutor2, 
  SUM( CASE
    WHEN (R1.Rate > 6 && R2.Rate > 6) || 
                (R1.Rate < 7 && R2.Rate < 7) THEN 1
    ELSE 0 END) AS SIMILARITY
FROM (
    SELECT DISTINCT NameB AS Name
    FROM tbl_rating 
    WHERE RoleB='Tutor'
    UNION
    SELECT DISTINCT NameA AS Name
    FROM tbl_rating
    WHERE RoleA='Tutor'
    ORDER BY Name) AS T1
CROSS JOIN (
    SELECT DISTINCT NameB AS Name
    FROM tbl_rating 
    WHERE RoleB='Tutor'
    UNION
    SELECT DISTINCT NameA AS Name
    FROM tbl_rating
    WHERE RoleA='Tutor'
    ORDER BY Name) AS T2
CROSS JOIN (
    SELECT DISTINCT NameB AS Name
    FROM tbl_rating 
    WHERE RoleB='Student'
    UNION
    SELECT DISTINCT NameA AS Name
    FROM tbl_rating
    WHERE RoleA='Student'
    ORDER BY Name) AS Student
LEFT JOIN tbl_rating AS R1
ON T1.Name = R1.NameA
AND Student.Name = R1.NameB
LEFT JOIN tbl_rating AS R2
ON T2.Name = R2.NameA
AND Student.Name = R2.NameB
WHERE Tutor1 < Tutor2
GROUP BY Tutor1, Tutor2
ORDER BY Tutor1, Tutor2

您可以通过在他们自己的表中提取学生和导师的特定数据,将评分表拆分为学生评分和导师评分,并使用外键来提高这些查询的效率:

Table student : Id | Name
Table tutor: Id  | Name
Table tutor_rating: StudentId | TutorId | Rate
Table student_rating: StudentId | TutorId | Rate

可能还有一个tutor_similiarity表来避免一直重新计算整个数据集,并在评级表上使用几个触发器来更新它(相似性计算将是增量的,查询只会转储其内容)。

Table tutor_similarity: TutorId1 | TutorId2 | Similarity
于 2013-03-24T22:15:59.813 回答
0

这确实是一条评论,但评论太长了。

首先,您不能轻松地创建具有可变列数的表。你提前知道这些列吗?通常,您以在原始 table 中的方式表示矩阵。. . “x”和“y”值是列,值位于第三列。

其次,xand是o基于导师对学生的评分,反之亦然?你的问题完全模棱两可。

第三,要将评分转换为“x”或“o”,只需使用 case 语句:

select (case when rating >= 7 then 'x' else 'o' end)

第四,你说A到B、C、D的相似度分别是0、2、3。我不知道你是如何从你展示的矩阵中得到这个的。如果是“x”的重叠,那么这些值似乎是 0、1 和 2。

我的最终结论是,您根本不需要创建这样的矩阵,因为您已经拥有正确格式的数据。

于 2013-03-24T22:07:20.240 回答