我需要帮助编写复杂的排除SQL查询(至少对我而言)。首先,我在这里描述需求和查询......
说
我有一个表“my_users”,其中维护了用户名和user_ids。
我有一张表“my_skills”,其中我保留了一个技能名称和相应的skill_id。
我有一个表“my_users_skills”,其中维护用户及其相应的skill_id。
我有一个表“my_companies”,其中我保留了公司名称和相应的company_ids。
我有一张表“my_employer_profile”,其中包含雇主用户ID和雇主公司身份
我有一个表“my_users_blocked_companies”,它包含用户ID和相应的被阻止的公司ID。 “my_users_blocked_companies”表的目的是为用户维护一个或多个公司作为被阻止的公司。
当一家公司的HR人员搜索用户时,将该公司(人力资源部门正在工作)设置为被阻止公司的用户不应该进入搜索结果。
让我们进入SQL查询
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);
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");
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);
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");
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”是摩托罗拉公司的一名员工。
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
搜索结果,考虑到被封锁的公司将取得凯利的记录,因为约翰已将摩托罗拉定为封锁公司,而克里希纳则来自摩托罗拉
对于这种情况,我遇到了很多困难,但却无法编写正确的查询。
答案 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