SQL排除JOIN查询 - 需要帮助

时间:2012-11-28 22:52:38

标签: mysql join

我需要帮助编写复杂的排除SQL查询(至少对我而言)。首先,我在这里描述需求和查询......

  1. 我有一个表“my_users”,其中维护了用户名和user_ids。

  2. 我有一张表“my_skills”,其中我保留了一个技能名称和相应的skill_id。

  3. 我有一个表“my_users_skills”,其中维护用户及其相应的skill_id。

  4. 我有一个表“my_companies”,其中我保留了公司名称和相应的company_ids。

  5. 我有一张表“my_employer_profile”,其中包含雇主用户ID和雇主公司身份

  6. 我有一个表“my_users_blocked_companies”,它包含用户ID和相应的被阻止的公司ID。 “my_users_blocked_companies”表的目的是为用户维护一个或多个公司作为被阻止的公司。

  7. 当一家公司的HR人员搜索用户时,将该公司(人力资源部门正在工作)设置为被阻止公司的用户不应该进入搜索结果。

    让我们进入SQL查询

    1

    DROP TABLE IF EXISTS my_users;
    
    CREATE TABLE my_users
    (
    user_id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name varchar(20) NOT NULL UNIQUE,
    age int NULL
    )
    
    
    INSERT INTO my_users VALUES
    (1, "John", 20),
    (2, "Kelly", 25),
    (3, "Xavier", 50),
    (4, "Krishna", 40);
    

    2

    DROP TABLE IF EXISTS my_skills;
    
    CREATE TABLE my_skills
    (
    skill_id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    skill varchar(20) NOT NULL UNIQUE
    );
    
    
    INSERT INTO my_skills VALUES
    (1, "MySql"),
    (2, "Php"),
    (3, "Linux"),
    (4, "Java");
    

    3

    DROP TABLE IF EXISTS my_users_skills;
    
    CREATE TABLE my_users_skills
    (
    user_id int NOT NULL,
    skill_id int NOT NULL
    );
    
    INSERT INTO my_users_skills VALUES
    (1,2),
    (1,4),
    (2,1),
    (2,4),
    (3,2),
    (3,3);
    

    4

    DROP TABLE IF EXISTS my_companies;
    
    CREATE TABLE my_companies
    (
    company_id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    company varchar(20) NOT NULL UNIQUE
    );
    
    
    INSERT INTO my_companies VALUES
    (1, "Motorola"),
    (2, "Logica"),
    (3, "Microsft"),
    (4, "Texas Instruements");
    

    5

    DROP TABLE IF EXISTS my_employer_profile;
    
    CREATE TABLE my_employer_profile
    (
    user_id int NOT NULL,
    comp_id int NOT NULL
    );
    
    INSERT INTO my_employer_profile VALUES
    (4,1),
    

    现在很明显,“Krishna”是摩托罗拉公司的一名员工。

    6

    DROP TABLE IF EXISTS my_users_blocked_companies;
    
    CREATE TABLE my_users_blocked_companies
    (
    user_id int NOT NULL,
    comp_id int NOT NULL
    );
    
    INSERT INTO my_users_blocked_companies VALUES
    (1,1),
    (1,4),
    (2,4)
    

    现在你可以清楚地看到约翰已经将摩托罗拉和德克萨斯州的Instruements设置为被封锁的公司。 凯利也将Texas Instruements设为封锁公司。

    现在,如果Krishna正在搜索具有'java','mysql'技能的用户,我们可以有两种可能的情况:

    <案例1

    搜索结果,不考虑被阻止的公司将获取John和Kelly的记录。

    此案例的SQL查询是

    SELECT x.name
    , GROUP_CONCAT(DISTINCT y2.skill ORDER BY y2.skill) skills
    FROM my_users x
    JOIN my_users_skills xy1
    ON xy1.user_id = x.user_id
    JOIN my_skills y1
    ON y1.skill_id = xy1.skill_id
    AND y1.skill IN ('java','mysql')
    JOIN my_users_skills xy2
    ON xy2.user_id = xy1.user_id
    JOIN my_skills y2
    ON y2.skill_id = xy2.skill_id
    GROUP
    BY x.user_id; 
    
    <案例2

    搜索结果,考虑到被封锁的公司将取得凯利的记录,因为约翰已将摩托罗拉定为封锁公司,而克里希纳则来自摩托罗拉

    对于这种情况,我遇到了很多困难,但却无法编写正确的查询。

1 个答案:

答案 0 :(得分:1)

你可以这样做:

SELECT x.name , GROUP_CONCAT(DISTINCT y2.skill ORDER BY y2.skill) skills 
   FROM my_users x 
   JOIN my_users_skills xy1 
       ON xy1.user_id = x.user_id 
   JOIN my_skills y1 
       ON y1.skill_id = xy1.skill_id AND y1.skill IN ('java','mysql') 
   JOIN my_users_skills xy2 
       ON xy2.user_id = xy1.user_id 
   JOIN my_skills y2 
       ON y2.skill_id = xy2.skill_id 
   GROUP BY x.user_id 
       HAVING x.user_id NOT IN (
         SELECT bc.user_id FROM my_users_blocked_companies bc 
         LEFT JOIN my_companies c ON bc.comp_id = c.company_id
         WHERE c.company IN ('Motorola')
       );

sqlfiddle execution here