加入两个多对多关系,“全部”运营商

时间:2011-05-20 03:00:18

标签: sql join many-to-many

我有四个值表:教师,证书,block_subjects和块以及两个关系表:instructor_certifications和subject_certification。像这样:

block -- block_subject
          |
          |
 subject_certification
          |
          |
     certification 
          |
          |
instructor_certification
          |
          |
      instructor

我想要一个能告诉我的查询,每个块的 ,哪些教师有资格教这个块。具体来说,我不想将块id指定为查询的一部分;我想根据不同的标准选择多个块。

以下是我目前的(非工作)查询:

select inst.name, inst.id
from instructor as inst
join instructor_certification as ic on inst.id = ic.instructor_fid and
ic.certification_fid = all (
   select cert.id
   from block_subject as bs 
   join subject_certification as bsc on bsc.block_fid = bs.id
   join certification as cert on bsc.certification_fid = cert.id
   where bs.id = any (
       select bs.id
   from block as b
       join block_subject as bs on b.subject_fid = bs.id
       where (b.start_date, b.end_date) overlaps (?, ?)
   )
)

显然,这不起作用,因为'all'收集日期范围内每个block_subject所需的所有认证。

编辑:我还应该澄清,每个block_subject需要多次认证。

3 个答案:

答案 0 :(得分:1)

编辑后:

每位教师每个区块需要多个证书:

 select b.id as blockid, bs.subject_id as subject_id, i.id as inscructorid, count(ic.certification_id) as numCerts
 from block b
 join block_subject bs on b.id = bs.block_id
 join subject_certification sc on bs.subject_id = sc.subject_id
 join instructor_certification ic on sc.certification_id = ic.certification_id
 join instructor i on ic.instructor_id = i.id
 group by b.id, bs.subject_id, i.id
 having count(ic.certification_id) > 1

您的问题是“每个街区”。所以,从块开始,然后进行连接。像这样:

 select *
 from block b
 join block_subject bs on b.id = bs.block_id
 join subject_certification sc on bs.subject_id = sc.subject_id
 join instructor_certification ic on sc.certification_id = ic.certification_id
 join instructor i on ic.instructor_id = i.id

您现在可以添加所需的任何条件。

特定区块?

 where b.id = @inid

日期范围?

 where @Date between b.start_date and b.end_date

讲师?

 where i.id = @inid

认证?

 where c.id = @inid

或组合。

答案 1 :(得分:0)

给这一点。

declare @Date datetime

set @Date = '01/01/2011'

select inst.name, inst.id
from instructor as inst
join instructor_certification as ic on inst.id = ic.instructor_fid 
and ic.certification_fid in (
   select cert.id
   from block_subject as bs 
   join subject_certification as bsc on bsc.block_fid = bs.id
   join certification as cert on bsc.certification_fid = cert.id
   where bs.id in (select bs.id 
       from block as b
       join block_subject as bs on b.subject_fid = bs.id
       where @Date between b.start_date and b.end_date ) )
   ) x

答案 2 :(得分:0)

只是教练......

 select
    i.*
 from
    instructor i on 
 where
    exists (
     select *
     from
        block b
        join block_subject bs on b.id = bs.block_id
        join subject_certification sc on bs.subject_id = sc.subject_id
        join instructor_certification ic on sc.certification_id = ic.certification_id
      WHERE 
        ic.instructor_id = i.id
        AND
        ..other filters here
        )