1

在 SQL Server (2008) 中,我想在一个表中找到所有具有 3、4、5 或 4、5、6 技能 ID 的员工。他们需要其中一组。例如,仅具有 Skillid=4 不应产生匹配。如何构建这种类型的查询?

一个示例表:

pkid, empid, skillid
 1     2       3
 2     2       4
 3     2       5
 4     5       6

在上面的例子中,empid=2 匹配集合 3,4,5。empid=5 不是。

4

5 回答 5

4

您将需要在查询中使用一个GROUP BY和一个HAVING子句:

select empid
from t1
where skillid in (3, 4, 5) 
    or skillid in (4, 5, 6) 
group by empid
having count(distinct skillid) = 3

请参阅带有演示的 SQL Fiddle

于 2012-08-15T21:11:09.623 回答
2

我对您最初问题的阅读是,您想找到满足以下任一条件的员工:

  • 他们的技能 ID 为 3 和 4 和 5
  • 他们的技能 ID 为 4 和 5 和 6

(或两者)。如果是这种情况,您将需要使用相关子查询来执行类似的操作:

select *
from employee e
where (     exists ( select * from employee_skill es3 on es3.empid = e.empid and es3.skillid = 3 )
        and exists ( select * from employee_skill es3 on es3.empid = e.empid and es3.skillid = 4 )
        and exists ( select * from employee_skill es3 on es3.empid = e.empid and es3.skillid = 5 )
      )
   OR (     exists ( select * from employee_skill es3 on es3.empid = e.empid and es3.skillid = 4 )
        and exists ( select * from employee_skill es3 on es3.empid = e.empid and es3.skillid = 5 )
        and exists ( select * from employee_skill es3 on es3.empid = e.empid and es3.skillid = 6 )
      )

但是,由于您的两个目标技能集 { 3, 4, 5 } 和 { 4, 5, 6 } 具有公共子集 { 4 , 5 },因此我们可以简化。重构,我们得到

select *
from employee e
where exists ( select * from employee_skill es3 on es3.empid = e.empid and es3.skillid =    4       )
  and exists ( select * from employee_skill es3 on es3.empid = e.empid and es3.skillid =    5       )
  and exists ( select * from employee_skill es3 on es3.empid = e.empid and es3.skillid in ( 3 , 6 ) )

另一种技术是使用left join

select *
from employee e
left join employee_skill es3 on es3.empid = e.empid and es3.skillid = 3
left join employee_skill es4 on es4.empid = e.empid and es4.skillid = 4
left join employee_skill es5 on es5.empid = e.empid and es5.skillid = 5
left join employee_skill es6 on es6.empid = e.empid and es6.skillid = 6
where es4.empid is not null
  and es5.empid is not null
  and (    es3.empid is not null
        OR es6.empid is not null
      )

后一种方法使用left join包含一个隐含的假设,即特定员工/技能组合在数据模型中是唯一的。如果不是这种情况,那么这种方法将需要使用,select distinct以免您在结果集中获得重复的行。

于 2012-08-15T22:05:41.713 回答
1

尝试

select pkid, empid
from your_table
where skillid in (3,4,5) or skillid in (4,5,6) 
group by pkid, empid
having count(distinct skillid) = 3
于 2012-08-15T21:07:36.103 回答
1

先前的两个答案都无法区分 (1,2,6) 或 (1,5,6) 或 (2,5,6) 等中的集合成员资格。结果必须只显示一个 empid ALL of 1,2,3 OR 4,5,6 的成员。

尝试:

    创建表Table1(pkid int 约束PK_Table1 主键,empid int,skillid int)

    插入 table1 值 (1,2,1)
    插入 table1 值 (2,2,2)
    插入 table1 值 (3,2,3)
    插入 table1 值 (4,3,1)

    选择 empid
    从 (
        SELECT empid, sum(t.s1) as s1, sum(t.s2) as s2, sum(t.s3) as s3, sum(t.s4) as s4, sum(t.s5) as s5, sum( t.s6) 作为 s6
        从
        (
            选择 empid, 1 s1, 0 s2, 0 s3, 0 s4, 0 s5, 0 s6
            从表 1
            其中skillid = 1
            联合所有
            选择 empid, 0, 1, 0, 0, 0, 0
            从表 1
            其中skillid = 2
            联合所有
            选择 empid, 0, 0, 1, 0, 0, 0
            从表 1
            其中skillid = 3
            联合所有
            选择 empid, 0, 0, 0, 1, 0, 0
            从表 1
            其中skillid = 4
            联合所有
            选择 empid, 0, 0, 0, 0, 1, 0
            从表 1
            其中skillid = 5
            联合所有
            选择 empid, 0, 0, 0, 0, 0, 1
            从表 1
            其中skillid = 6
        ) 吨
        按 t.empid 分组
    ) tt
    WHERE (tt.s1 = 1 and tt.s2 = 1 and tt.s3 = 1) or (tt.s4 = 1 and tt.s5=1 and tt.s6=1)
于 2012-08-15T21:23:07.677 回答
0

empid IN (3,4,5) 是 empid = 3 或 empid = 4 或 empid = 5 的简写,所以 empid IN 3,4,5, OR empid IN (4,5,6) 与 empid IN ( 3,4,5,6)。但是,我们需要避免用 3、5、6 或 3、4、6 来计算人。你可以这样做:

SELECT empid, 345 AS skillset
FROM your_table
WHERE skillid IN (3,4,5)
GROUP BY empid
HAVING COUNT(DISTINCT skillid) = 3
UNION ALL
SELECT empid, 456 AS skillset
FROM your_table
WHERE skillid IN (4,5,6)
GROUP BY empid
HAVING COUNT(DISTINCT skillid) = 3

如果您想查看哪个 empid 有两个集合等,您可以在此周围放置一个 SELECT。

于 2012-08-15T21:29:21.263 回答