如何在连接条件下工作

时间:2017-03-19 15:23:54

标签: sql oracle

enter image description here

如何在提供ContactID时找到城市,条件是如果ContactID是123,那么它将查看它是P还是C,如果是P则它将转到Person表并返回City(USA)作为输出和If C然后它将转到公司表并给出City(AUS)作为输出。 注意:所有表都包含数千条记录,而City值来自运行时间。

3 个答案:

答案 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;

在您的情况下,这可能并不重要。但是,如果第二个连接匹配多个行且第一个匹配单个行,则可能不希望输出中的其他行。