2013-10-11 3 views
4

Пожалуйста, смотрите ниже DDL:саз в ЕКЕ

CREATE TABLE dbaddress 
(aid integer identity not null, link_id int, link_type char, primary key (aid)) 
CREATE TABLE dbDoorSupervisor 
(did integer identity not null, name varchar(30), primary key (did)) 
CREATE TABLE dbLicensee 
(lid integer identity not null, name varchar(30), primary key (lid)) 

INSERT INTO dbDoorSupervisor (name) values ('Ian') 
INSERT INTO dbLicensee (name) values ('Maria') 
INSERT INTO dbaddress (link_id, link_type) values (1,'D') 
INSERT INTO dbaddress (link_id, link_type) values (1,'L') 

Я пытаюсь получить имя двери супервизора или лицензиат в зависимости от Address.AID, который поставляется. Например, если в выражении WHERE предоставляется помощь 1, то Ian возвращается из таблицы диспетчера дверей, однако, если в предложении WHERE предоставляется помощь 2, то Maria возвращается из таблицы Licensee.

Я знаю, что вы можете использовать операторы CASE в предложении SELECT, но можете ли вы использовать их в предложении FROM i.e. Присоединиться от адреса к лицензиату или адресу к диспетчеру двери в зависимости от предоставленной AID?

+0

Нет, но вы могли бы присоединиться в обеих таблицах, а затем использовать случай в SELECT для чтения только соответствующего связанного имени для каждой строки. Или вы можете сделать два запроса, один из которых ищет один тип и один для другого типа, и объединить их вместе. –

+0

@JacobM, спасибо. Я думаю, что ответ заключается в создании производной таблицы, содержащей все дверные супервизоры и лицензиаты, как я думаю, вы подразумевали. – w0051977

ответ

0

Не без динамического SQL, который имеет свой собственный набор проблем.

Если ваша база данных просто так, только 2 или около возможностей, один простой способ, чтобы присоединиться как и иметь дело с результатами вручную, например:

select 
    a.aid 
    ,case a.link_type 
     when 'D' then ds.name 
     when 'L' then l.name 
    end [name] 
from 
    dbaddress a 
left join 
    dbDoorSupervisor ds on a.link_type = 'D' and a.link_id = ds.did 
left join 
    dbLicensee l on a.link_type = 'L' and a.link_id = l.lid 
+0

нет столбца link_id в dbDoorSupervisor и dbLicensee в схеме OP :) –

+0

@RomanPekar Исправлено. Спасибо, что поймал это. –

2
select a.linkd_id, 
case when link_type = 'D' then d.name 
    when link_type = 'L' then l.name 
end as 'Name' 
from dbAddress a 
left join dbDoorSupervisor d on d.did = a.link_id 
left join dbLicensee l on l.lid = a.link_id 
4

вы можете переключиться в left outer join раздел как это:

select 
    isnull(d.name, l.name) as name 
from dbaddress as a 
    left outer join dbDoorSupervisor as d on d.did = a.link_id and a.link_type = 'D' 
    left outer join dbLicensee as l on l.lid = a.link_id and a.link_type = 'L' 

Или присоединиться к так или иначе и перейти в сазе

select 
    case a.link_type 
     when 'D' then d.name 
     when 'L' then l.name 
    end as name 
from dbaddress as a 
    left outer join dbDoorSupervisor as d on d.did = a.link_id 
    left outer join dbLicensee as l on l.lid = a.link_id 

Если у вас есть более чем один столбец, чтобы показать, вы можете использовать внешний применить так что вы «не должны повторять случай:

select 
    c.name, c.address, c.second_name 
from dbaddress as a 
    left outer join dbDoorSupervisor as d on d.did = a.link_id 
    left outer join dbLicensee as l on l.lid = a.link_id 
    outer apply (
     select d.name, d.second_name, d.address where a.link_type = 'D' union all 
     select l.name, l.second_name, l.address where a.link_type = 'L' 
    ) as c 
+0

В качестве побочного примечания, если есть более двух комбинаций, и вы идете с помощью пути isnull, вы можете либо вложить их, как 'isnull (ds.name, isnull (dl.name, dx.name))' или go с [coalesce] (http://msdn.microsoft.com/en-us/library/ms190349.aspx) –

+0

@JoeEnos добавило решение для более чем одного столбца, его можно было легко расширить для нескольких комбинаций –