2

假设我们有一个这样的数据库:

Project_tbl

-----------------
编号 | 项目名称
-----------------
1 | 一个
2 | 乙
3 | C
-----------------

personel_project_tbl

--------------------
用户 ID | 项目编号
--------------------
1 | 1
2 | 2
3 | 1
3 | 2
2 | 3
--------------------

instrument_project_tbl

--------------------------
仪器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 没有共同的用户,但有 1 比 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. 这个问题是这个问题的补充问题:获取 MySQL 数据库中重复次数最多的相似字段,如果您的解决方案可以以某种方式用于它们两者(不知何故),那就太好了。我想将相关项目的价值与项目的相似性相乘以获得最佳选择......

总之,这两个问题将:获取最相关的项目,获取所有项目的相似项,并找到当前项目与当前项目最相似的项目!哟


感谢您的智慧回答,如果您能对这些情况有所了解,我们将不胜感激

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

想法是为每个表创建一个子查询,每个子查询将项目 ID 映射到给定表的对应比率。

关于性能,我什么都没说。您必须尝试看看它是否足够快以满足您的需求,但正如我所见,没有办法击败您提到的 O( n 2 ) 复杂性,因为您必须检查所有数据。

于 2012-07-25T06:37:31.877 回答