2

我需要帮助编写一个复杂的排除 sql 查询(至少对我来说)。首先,我在这里描述需求和查询......

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

  2. 我有一个表“my_skills”,我在其中维护技能名称和相应的技能 ID。

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

  4. 我有一个表“my_companies”,我在其中维护公司名称和相应的 company_ids。

  5. 我有一个包含雇主用户 ID 和雇主公司 ID 的表“my_employer_profile”

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

某公司HR人员搜索用户时,将该公司(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),

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

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)

现在您可以清楚地看到 John 已将 Motorola 和 Texas Instruments 设置为被封锁的公司。kelly 也将 Texas Instruments 设置为被封锁的公司。

现在,如果 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

搜索结果,考虑到被封锁的公司将获取凯利的记录,因为约翰已将摩托罗拉设置为被封锁的公司,而 Krishna 来自摩托罗拉

对于这种情况,我很努力,但无法编写正确的查询。

4

1 回答 1

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在这里执行

于 2012-11-28T23:09:27.363 回答