数据库 - 表设计和查询

时间:2012-02-04 05:56:56

标签: php mysql sql database select

我正在开发一个php程序,用户需要从下拉列表中选择技能(一个或多个) 然后我将结果保存在数组中: user_skills [] 然后每个项目都有一个必需技能列表,我将它保存在另一个数组中:proj_skills []

问题是: 将这些信息保存到数据库中的最佳方法是什么 我应该为项目技能和用户技能创建2个新表(列:proj_id和技能) 连续的每项技能,

什么是比较项目与用户技能并找到匹配技巧的最佳方法? 从user_skills中选择id,其中skill = proj_skill [i]和id IN(从user_skills中选择id,其中skill = Proj_skill [i + 1] .......嵌套select / loop或(递归)

怎么做,最好和最优化的方式是什么?

希望很清楚,在此先感谢:)

3 个答案:

答案 0 :(得分:1)

如果用户可以与多个项目相关联,并且项目可以与多个用户相关联,那么最好将用户和项目的技能存储在单独的表中。

在设置两个表之后,我会创建第三个表来保存所有可能的技能(我假设没有技能只能与用户或仅与项目相关联)。现在,您将拥有以下表,Users,Projects,UserSkills和ProjectSkills。

一旦设置了这些,并假设您可以将UserID和ProjectID传递给查询,我只会将用户技能与SkillID上的项目技能相结合。如,

SELECT Q1.UserID,
       Q1.Skill
FROM   (SELECT Users.UserID,
               Skills1.Skill,
               Skills1.SkillID
        FROM   Users
               INNER JOIN UserSkills
                 ON Users.UserID = UserSkills.UserID
               INNER JOIN Skills AS Skills1
                 ON UserSkills.SkillID = Skills1.SkillID
        WHERE  Users.UserID = 123) AS Q1
       INNER JOIN (SELECT Projects.ProjectID,
                          Skills2.Skill,
                          Skills2.SkillID
                   FROM   Projects
                          INNER JOIN ProjectSkills
                            ON Projects.ProjectID = ProjectSkills.ProjectID
                          INNER JOIN Skills AS Skills2
                            ON Project.SkillID = Skills2.SkillID
                   WHERE  ProjectID = 456) AS Q2
         ON Q1.SkillID = Q2.SkillID;

通常,您希望避免在使用SQL时进行迭代。你最好的表现就是要求你只想要一次。此外,如果你按照上面所写的方式进行迭代,那么你假设所有的ID都是顺序​​的,但是技能不可能(并且很可能)。所以,这两个人可能有共同的技能1和3,但不是2.你会在技能2上没有任何共同点后停止你的循环吗?你必须在sets中思考。另外,请注意IN子句。如果您尝试测试以查看某些内容是否为“NOT IN”包含null的结果集,即使您的用户和项目具有相同的技能,也不会收到任何结果。这是一篇关于http://bharatmane.com/blog/?p=52

主题的文章

答案 1 :(得分:1)

我不知道这是否是最佳或最优化的方式,但这是一种方法。 :)

首先,您需要的表格:(为简单起见,我省略了名称栏等)

CREATE TABLE skills (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (id)
) ENGINE=InnoDB;

CREATE TABLE users (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (id)
) ENGINE=InnoDB;

CREATE TABLE projects (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (id)
) ENGINE=InnoDB;

CREATE TABLE user_skills (
    user_id INT UNSIGNED NOT NULL,
    skill_id INT UNSIGNED NOT NULL,
    PRIMARY KEY (user_id, skill_id),
    FOREIGN KEY (user_id) REFERENCES users (id),
    FOREIGN KEY (skill_id) REFERENCES skills (id)
) ENGINE=InnoDB;

CREATE TABLE project_skills (
    project_id INT UNSIGNED NOT NULL,
    skill_id INT UNSIGNED NOT NULL,
    PRIMARY KEY (project_id, skill_id),
    FOREIGN KEY (project_id) REFERENCES projects (id),
    FOREIGN KEY (skill_id) REFERENCES skills (id)
) ENGINE=InnoDB;

如果您想要显示至少具有编号为1,3和5的技能的所有用户:

SELECT user_id
FROM user_skills
WHERE skill_id IN (1, 3, 5)
GROUP BY user_id
HAVING COUNT(*) = 3;

因此,我们首先使用where子句过滤掉所有不相关的技能,然后按用户分组。之后,COUNT(*)告诉我们每个用户有多少匹配技能。然后,having子句仅显示具有3种匹配技能的用户,这意味着这些用户至少拥有我们正在寻找的技能。

如果您想要显示具有技能1,3和5但没有其他技能的所有用户:

SELECT s1.user_id
FROM (
    SELECT user_id, COUNT(*) count
    FROM user_skills
    GROUP BY user_id
) s1
INNER JOIN (
    SELECT user_id, COUNT(*) count
    FROM user_skills
    WHERE skill_id IN (1, 3, 5)
    GROUP BY user_id
) s2 ON (s1.user_id = s2.user_id)
WHERE s1.count = 3 AND s2.count = 3;

此处,第一个子查询查找每个用户的总技能数,第二个子查询查找每个用户的匹配技能数。如果两者都是3,则用户具有我们正在寻找的技能。

如果您想找到所有“兼容”的用户和项目,即所有(项目,用户) - 用户至少具有项目所需技能的所有(项目,用户) -

SELECT s2.project_id, s2.user_id
FROM (
    SELECT project_id, COUNT(*) count
    FROM project_skills
    GROUP BY project_id
) s1
INNER JOIN (
    SELECT project_skills.project_id, user_skills.user_id, COUNT(*) count
    FROM project_skills
    INNER JOIN user_skills ON (user_skills.skill_id = project_skills.skill_id)
    GROUP BY project_skills.project_id, user_skills.user_id
) s2 ON (s1.project_id = s2.project_id)
WHERE s2.count = s1.count;

这里,第一个子查询找出每个项目所需的技能数量。第二个子查询找出每个(项目,用户)对的常用技能。它通过加入project_skillsuser_skills技能,然后按项目和用户进行分组来实现此目的。之后,COUNT(*)会告诉每个项目和用户有多少常用技能。最后,我们加入两个子查询,只显示(项目,用户) - 共同技能的数量等于项目所需技能的数量。

答案 2 :(得分:0)

我不是一个php编码器,所以你的一些问题传递给我,但在数据库设计方面,你需要三个表:人员,技能和技能人员。后一个表是一个“链接表”,至少有两个字段作为联合主键:人和技能。您可以在此表中添加该人拥有该技能的程度。

如果你有一个项目表和另一个链接表来获得该项目所需的所有技能,那么为了找到拥有该项目所需技能的人,你需要写下这样的东西:

select people.name, skills.name
from people inner join skillsperperson on people.id = skillsperperson.person
inner join skills on skillsperperson.skill = skills.id
inner join skillsperproject on skills.id = skillsperproject.skill
where skillsperproject = :p1;  

(:p1是您传递给查询的参数;其值将是给定项目的ID)。