2

次のようなデータベースがあると仮定しましょう。

Project_tbl

-----------------
id | Project_name
-----------------
1 | A
2 | B
3 | C
-----------------

personel_project_tbl

--------------------
user_id | Project_id
--------------------
1 | 1
2 | 2
3 | 1
3 | 2
2 | 3
--------------------

instrument_project_tbl

--------------------------
Instrument_id | Project_id
--------------------------
1 | 1
1 | 2
2 | 2
2 | 1
1 | 3
--------------------------

次に、プロジェクトのリストを並べ替えて、プロジェクトAとの類似性に関してランク付けする必要があります。

例えば:

AとBには、3人のユーザーに対して1人のユーザーが共通しており、2人の楽器に対して2人の楽器があるため、類似性のランク付けは(1/2 + 2/2)/ 2 = 75%です。

AとCには共通のユーザーはありませんが、2つ以上の楽器があるため(1/2)/ 2 = 25%になります

したがって、Bはbeよりも類似しており、出力は

--------------
プロジェクト| ランク
--------------
2 | 75
3 | 25

それが私の頭に浮かんだ最初の解決策です...
PHPとMySQLでそれを行った場合、次のようになります。

 for all tables as table_x
    for all projects (except A) as prj_y
         unique = (Select distinct count(items) from table_x where project is A)
         count += (Select distinct count(items) from table_x
                   where project is prj_x and items are in
                     (select distinct items from table_x where project is a)
                  )/unique

したがって、複雑さはO(n 2)になり、インデックスを作成すると、選択のコストもO(log n)になり、手頃な価格にはなりません。

MySQLで完全に実行する、またはより適切で高速な方法で実行するアイデアはありますか?

********詳細と注意事項:**

  1. 私はPHPとMySQLに制限されています。

  2. これは単なる例です。私の実際のプロジェクトでは、テーブルは20を超えるテーブルであるため、ソリューションは高性能である必要があります。

  3. この質問は、この質問の補足質問です。yrソリューションを両方に使用または適用できる場合は、MySQLデータベースで最も繰り返される類似フィールドを取得します(どういうわけか)。関連するプロジェクトの価値にアイテムの類似性を掛けて、最良のオプションを取得したい...

結論として、これらの2つの質問は、最も関連性の高いプロジェクトを取得し、すべてのプロジェクトの類似アイテムを取得し、プロジェクトが現在のものと類似している現在のプロジェクトの最も類似したアイテムを見つけることです。よ


あなたの知的な答えに感謝します、あなたが状況にいくらかの光を当てることができればそれは本当にありがたいです

4

1 に答える 1

0

あなたはこのようにそれを行うことができます:

SET @Aid = (SELECT id
            FROM Project_tbl
            WHERE Project_name = 'A');

SELECT P.id
  , (IFNULL(personel.prop, 0) +
     IFNULL(instrument.prop, 0)
    )/2*100 Rank
  , personel.prop AS personell
  , instrument.prop AS instrument
FROM Project_tbl P
LEFT JOIN
  ( SELECT B.Project_id pid, COUNT(*)/C.ref prop
    FROM personel_project_tbl A,
         personel_project_tbl B,
         (SELECT COUNT(*) AS ref
          FROM personel_project_tbl
          WHERE Project_id = @Aid
         ) AS C
    WHERE A.user_id = B.user_id
    AND A.Project_id = @Aid
    GROUP BY B.Project_id
  ) personel ON P.id = personel.pid
LEFT JOIN
  ( SELECT B.Project_id pid, COUNT(*)/C.ref prop
    FROM instrument_project_tbl A,
        instrument_project_tbl B,
         (SELECT COUNT(*) AS ref
          FROM instrument_project_tbl
          WHERE Project_id = @Aid
         ) AS C
    WHERE A.instrument_id = B.instrument_id
    AND A.Project_id = @Aid
    GROUP BY B.Project_id
  ) instrument ON P.id = instrument.pid
WHERE P.id <> @Aid
ORDER BY Rank DESC

アイデアは、テーブルごとに1つのサブクエリを作成することです。これらのサブクエリはそれぞれ、プロジェクトIDを特定のテーブルの対応率にマップします。

パフォーマンスについては何も言っていません。ニーズに十分対応できるかどうかを確認する必要がありますが、すべてのデータを検査する必要があるため、言及したO( n 2 )の複雑さに打ち勝つ方法はありません。

于 2012-07-25T06:37:31.877 に答える