Соедините два отношения «многие ко многим», оператор «все» - PullRequest
1 голос
/ 20 мая 2011

У меня есть четыре таблицы значений: инструкторы, сертификаты, block_subjects и блоки и две таблицы отношений: instructor_certification и subject_certification.Например:

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

Я хочу запрос, который скажет мне, для каждого блока , который инструкторы имеют право обучать блок.В частности, я не хочу указывать идентификатор блока как часть запроса;Я хочу выбрать несколько блоков на основе разных критериев.

Вот (нерабочий) запрос, который у меня сейчас есть:

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 ]

1 голос
/ 20 мая 2011

После редактирования:

Требуется несколько сертификатов на блок на учителя:

 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

или их комбинация.

0 голосов
/ 20 мая 2011

только инструкторы ...

 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
        )
0 голосов
/ 20 мая 2011

Дайте этому шанс.

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
...