如何在提供ContactID时找到城市,条件是如果ContactID是123,那么它将查看它是P还是C,如果是P则它将转到Person表并返回City(USA)作为输出和If C然后它将转到公司表并给出City(AUS)作为输出。 注意:所有表都包含数千条记录,而City值来自运行时间。
答案 0 :(得分:3)
除非您动态生成查询(即使用SQL之外的某种语言来执行查询),否则无论如何都需要加入两个表。如果你加入这两个表,那么就不需要CASE声明了:
select *
from contacts co
left outer join person p
on co.contactid = p.contactid
and co.person_company = 'P'
left outer join company c
on co.contactid = c.contactid
and co.person_company = 'C'
您将开始在这里注意一个问题,对于PERSON和COMPANY的每一栏,您将不得不添加一些业务逻辑来确定您希望从哪个表中获取信息。这可能会非常烦人
select co.contactid
, case when p.id is not null then p.name else c.name end as name
from contacts co
left outer join person p
on co.contactid = p.contactid
and co.person_company = 'P'
left outer join company c
on co.contactid = c.contactid
and co.person_company = 'C'
您的PERSON和COMPANY表似乎在其中具有完全相同的信息。如果在您的实际数据模型中这是真的,那么就不需要将它们拆分。您可以确定每个实体是您的CONTACTS表中的个人还是公司。
只有在需要存储其他数据时,才能以这种方式创建其他表来存储数据。即便如此,我仍然会在一个表中为一个人或一个伙伴(即姓名或地址)提供相同的数据。
如果CONTACTID和PID以及CONTACTID和CID之间存在1-2-1关系,这是您的示例数据所暗示的,那么您有许多其他ID,这些ID没有任何价值。
最后,如果您没有限制,只有公司可以进入公司表和PERSON表中的个人。您需要PERSON_COMPANY列存在于PERSON和COMPANY中,但作为固定字符串。将此数据模型设置为以下内容更为正常:
create table contacts (
id integer not null
, contact_type char(1) not null
, name varchar2(4000) not null
, city varchar2(3)
, constraint pk_contacts primary key (id)
, constraints uk_contacts unique (id, contact_type)
);
create table people (
id integer not null
, contact_type char(1) not null
, some_extra_info varchar2(4000)
, constraint pk_people primary key (id)
, constraint fk_people_contacts
foreign key (id, contact_type)
references contacts (id, contact_type)
, constraint chk_people_type check (contact_type = 'P')
);
等
答案 1 :(得分:1)
您可以LEFT JOIN
所有3个表格并使用CASE
语句根据P或C值选择您需要的表格
SELECT
CASE c.[Person/Company]
WHEN 'P' THEN p.NAME
WHEN 'C' THEN a.Name
END AS Name
FROM Contact c
LEFT JOIN Person p on p.ContactId = c.ContactId
LEFT JOIN Company a on a.ContachId = c.ContactId
答案 2 :(得分:1)
Ben的回答几乎是正确的。在执行第二个连接之前,您可能想要检查第一个连接是否匹配:
select c.*, coalesce(p.name, c.name) as p.name
from contacts c left outer join
person p
on c.contactid = p.contactid and
c.person_company = 'P' left join
company co
on c.contactid = co.contactid and
c.person_company = 'C' and
p.contactid is null;
在您的情况下,这可能并不重要。但是,如果第二个连接匹配多个行且第一个匹配单个行,则可能不希望输出中的其他行。