2013-05-30 63 views
0

我想写下面的查询,以便从jobs表中返回职业和子职业对等于某个用户的职业和子职业对之一的所有职位( 4对中的一个)。如果用户有一对在subprofession = 0,这意味着采取相应的行业全部subprofessions:正确的SQL查询语法和WHERE EXISTS替代方案

是这样的:

select * from jobs j 
where 
     (j.profession, j.subprofession) in 

     (select (u.profession1, u.subprofession1) from users u where [email protected]), 
     select (u.profession2, u.subprofession2) from users u where [email protected]), 
     select (u.profession3, u.subprofession3) from users u where [email protected]), 
     select (u.profession4, u.subprofession4) from users u where [email protected]) 
and 
j.profession in (select u.profession1, u.profession2, u.profession3, u.profession4 from users u where [email protected]) 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) 

请求的查询会从工作表中的行返回: 1,2,3,4,11

这些地方的职业和subprofession的值(一对)出现在列其中一个用户prof和subprof对。另外,因为对于用户1有一个条目(prof3 = 100和subprof3 = 0),查询应该返回proession为100的所有订单(针对所有子协议)。

+3

*** SQL ***只是*结构化查询语言* - 许多数据库系统使用的语言,但不是数据库产品......许多东西都是特定于供应商的 - 所以我们真的需要知道什么* *您正在使用的数据库系统**(以及哪个版本)(请相应地更新标签)...... –

+0

查询 – Friederike

+0

有一些示例表和预期结果也是有用的这不清楚:'如果用户有一对,其中subprofession = 0,这意味着采取所有专业为各自职业' – Tim

回答

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来unpivot的数据,这样你可以内部连接并确定作业是否匹配,因为子行业为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

+0

尽管使用了exists关键字,第一个查询是否也会在ms访问环境中工作? – vobs

+0

是的,Access支持'EXISTS',所以第一个查询会正常工作。 – GarethD

0

我宁愿看两年前书写的查询是自记录比在一个地方我必须解出它在做什么。当然,对我来说这是一个困惑的东西,可能是别人的易如反掌。

考虑到subprofession插槽中通配符为零的意思,意思是“匹配行业,不用担心子行业”,我会将查询作为两个集合的联合。

第1组是所有与subprofession = 0的用户职业相匹配的作业的集合。
第2组是所有匹配用户的职业/子行业dyad的职位的集合。

因此,第一步是针对每个用户,获取不同行业的子列表不重要的列表。这使得内部人员加入到专业工作中。

第二步是为每个用户获得不同二元组的列表,即子业务的重要性。这使得内部加入了专业和子行业的工作。

如果您愿意,每个连接可以在第一组中添加一个表示MatchLevel的专栏,即ProfessionOnly,然后您可以看到同一个工作列出两次,一次用于一般匹配,一次用于特定比赛。