3

画像は私のテーブルの構造を示しています。最初の行は、tutorB が StudentD に 10 点を与えることを意味します。2 行目は、tutorE がまだ StudentD に何の評価も与えていないことを意味します。

ここに画像の説明を入力

次のテーブルを生成するにはどうすればよいですか? stackoverflow.com の別の投稿を参照しました。MySQL での協調フィルタリング? それでも、私はまだかなり混乱しています。

ここに画像の説明を入力

上記の画像から、o は推奨を意味し、レートは 7 以上です。x は推奨されないことを意味し、比率は 7 未満です。

たとえば、tutorB は StudentD に 10 点を与えます。したがって、画像の 2 行目から、StudentD 列に「o」があることがわかります。(そして、他の 3 つの行のデータは、現在ランダムに割り当てられています。)

ここで、ある生徒を家庭教師 A に推薦するとします。家庭教師 B、C、および D のランク (または類似度) は、それぞれ 0、2、および 3 です。

レートを「o」と「x」に変換してランクを計算できるように SQL を生成するにはどうすればよいですか。そして、最も重要なことは、画像のように StudentH を TutorA に推薦したいということです。

前回の投稿のコードをどのように変更すればよいですか? そして、上記の私の考えが正しければ?

ありがとう。

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

編集済み

データベースに次のデータがあります。最初の行は、tutorA が StudentC に 10 点を与えることを意味します。

ここに画像の説明を入力

分かりやすいように、別の表に変換します。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;

上記のコードは、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

DB スキーマは、実際には操作が簡単ではありません。

網羅的な評価テーブルを取得するクエリは次のとおりです。

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) とすべての生徒のリスト (2 番目のサブクエリStudent) を抽出することによって機能し、両方のセットの積を実行して、チューターと生徒のすべての可能な組み合わせを取得します。次に、評価テーブルとの外部結合を行います。これにより、生徒がチューターに対して行ったすべての評価が検索され、NULL存在しない評価が埋められます。(反対の評価を取得するためのクエリ-つまり、チューターによる学生の評価-は、スワッピングNameAと句で取得できます)NameBLEFT JOINCASE、要求に応じて数値 (または null) 評価をシンボルに変換します。

類似性のために、さらに 2 つの結合を追加する必要があります。

  • もう一つTutor
  • そしてもう1つ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」の値は列で、値は 3 番目の列に入ります。

第二に、教師から生徒への評価、またはその逆の評価に基づいていますかx? oあなたの質問は完全にあいまいです。

第 3 に、評価を「x」または「o」に変換するには、case ステートメントを使用します。

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

第 4 に、A から B、C、および D への類似度は、それぞれ 0、2、および 3 であると言います。あなたが示したマトリックスからどのようにこれを取得しているのかわかりません。「x」が重なっている場合、値は 0、1、および 2 に見えます。

私の最終的な結論は、正しい形式のデータが既にあるため、そのようなマトリックスを作成する必要はまったくないということです。

于 2013-03-24T22:07:20.240 に答える