我想编写以下查询,以便从jobs表中返回所有作业,其中专业和子专业对等于特定用户(4对中的一对)的专业和子专业对之一。如果用户有一对subprofession = 0,这意味着采取相应职业的所有子职业:
类似的东西:
select * from jobs j
where
(j.profession, j.subprofession) in
(select (u.profession1, u.subprofession1) from users u where userid=@userid),
select (u.profession2, u.subprofession2) from users u where userid=@userid),
select (u.profession3, u.subprofession3) from users u where userid=@userid),
select (u.profession4, u.subprofession4) from users u where userid=@userid)
and
j.profession in (select u.profession1, u.profession2, u.profession3, u.profession4 from users u where userid=@userid) and (u.subprofession1 = 0 or u.subprofession2 = 0 or u.subprofession3 = 0 or u.subprofession4 = 0))
我知道这个查询在语法上是错误的,并没有按照预期的那样做,那么使用IN子句或WHERE EXISTS实现上述目的的方法是什么?
jobs: profession, subprofession
1 (100, 200)
2 (100, 300)
3 (100, 400)
4 (100, 500)
5 (200, 300)
6 (400, 500)
7 (400, 100)
8 (400, 600)
9 (200, 200)
10 (600, 700)
11 (100, 100)
12 (500, 300)
13 (200, 200)
users: (prof1, subprof1, prof2, subprof2, prof3, subprof3, prof4, subprof4)
1 (100, 100, 757, 646, 100, 0, 500, 400)
2 (100, 2, 565, 76, 567, 534, 433, 565)
3 (200, 454, 553, 345, 354, 435, 334, 877)
4 (500, 300, 456, 565, 354, 435, 545, 435)
5 (400, 453, 434, 453, 423, 234, 324, 4435)
6 (100, 400, 435, 543, 465, 654, 454, 543)
7 (435, 435, 600, 700, 100, 0, 500, 400)
8 (100, 100, 553, 345, 100, 0, 500, 400)
请求的查询将从jobs表行返回: 1,2,3,4,11
这些行是专业和子专业(作为一对)的值出现在其中一个用户prof和subprof对中的行。另外,因为对于用户1,有一个条目(prof3 = 100和subprof3 = 0),查询应该返回所有命令为100的订单(对于所有子职业)。
答案 0 :(得分:1)
这应该适合你:
SELECT *
FROM Jobs
WHERE EXISTS
( SELECT 1
FROM Users
WHERE Users.UserID = @UserID
AND ( (Users.Profession1 = Jobs.Profession AND Users.SubProfession1 IN (Jobs.SubProfession, 0))
OR (Users.Profession2 = Jobs.Profession AND Users.SubProfession2 IN (Jobs.SubProfession, 0))
OR (Users.Profession3 = Jobs.Profession AND Users.SubProfession3 IN (Jobs.SubProfession, 0))
OR (Users.Profession4 = Jobs.Profession AND Users.SubProfession4 IN (Jobs.SubProfession, 0))
)
);
<强> Example on SQL Fiddle 强>
修改强>
由于它是SQL-Server,您可以使用CROSS APPLY..VALUES
来取消数据的移动,这样您就可以内连接并确定作业是否匹配,因为subprofession为0,或者是否存在精确的子伴随匹配:
WITH UserProf AS
( SELECT DISTINCT
Users.UserID,
p.Profession,
p.SubProfession
FROM Users
CROSS APPLY
(VALUES
(Profession1, SubProfession1),
(Profession2, SubProfession2),
(Profession3, SubProfession3),
(Profession4, SubProfession4)
) p (Profession, SubProfession)
WHERE Users.UserID = @UserID
)
SELECT Jobs.*,
MatchType = CASE WHEN MIN(UserProf.SubProfession) = 0 THEN 'All Subprofession' ELSE 'Exact subprofession' END
FROM Jobs
INNER JOIN UserProf
ON UserProf.Profession = Jobs.Profession
AND UserProf.SubProfession IN (0, Jobs.SubProfession)
GROUP BY Jobs.JobID, Jobs.Profession, Jobs.SubProfession;
<强> Example on SQL-Fiddle 强>
答案 1 :(得分:0)
我更愿意看一下两年前写的一个自我记录的问题,而不是我要弄清楚它在做什么的问题。当然,对我来说一些令人费解的事情可能是其他人的一切都很容易。
鉴于subprofession插槽中的通配符为零,意味着“匹配职业,不要担心子职业”,我会将查询视为两组联合。
Set 1是匹配用户职业的所有工作的集合,其中subprofession = 0 集合2是与用户的职业/子职业dyad匹配的所有作业的集合。
因此,第一步是为每个用户提供子职业无关紧要的不同职业的列表。这与职业就业有关。
第二步是为每个用户获取不同的二元组列表,即子职业的重要性。这与专业和子职业的就业有关。
如果你愿意,每个联接可以附加一个指示MatchLevel的列,即第一组中的ProfessionOnly和第二组中的Both,但是你可以看到两次列出相同的作业,一次用于一般匹配,一次用于特定匹配