使用左连接进行选择但未在连接表中显示数据

时间:2015-01-29 11:09:10

标签: sql oracle select join left-join

我有一个包含2个表的表结构

像这样的桌子人:

id name etc.   
1  test   
2  smith  
3  shaw

和第二个表人物,我记录了这样的名字的变化:所以,如果有人因为他结婚或类似的事情改变了他的名字,我仍然有旧的名字。

id personid name    etc.
1     1     oldtest

现在我有以下查询

select * from person p
Left join personhist ph on p.id = ph.personid
where (upper(p.name) = upper('oldtest') or upper(ph.name) like upper('oldtest'));

此查询将产生以下结果

id name    id personid name
1  test    1  1        oldtest

但我想只有实际的名字结果。所以问题是:有没有办法只显示来自" main"表格如果表格中有记录我加入了吗?

3 个答案:

答案 0 :(得分:3)

select p.*, coalesce(p.name, ph.name)
from person p
Left join personhist ph on p.id = ph.personid
where (upper(p.name) = upper('oldtest') or upper(ph.name) like upper('oldtest'))

答案 1 :(得分:2)

  

但是我想只有一个实体名称的结果。所以问题是有没有办法只显示来自" main"表格如果我加入的表中有记录吗?

只是不要包含您不想要显示的列。您正在使用 SELECT * ,这对任何生产系统来说都不是一件好事。您应该只指定所需的列名。

如果您确实要显示其中一个表的所有列,那么,在您的查询中,因为您已经拥有表名的别名,请使用相同的别名仅包含该表表格栏目。

select p.* - 这将包含表persons的所有列,其别名为p

select ph.* - 这将包含表personhist的所有列,其别名为ph

要仅包含选定的列,请明确提及它们。例如 -

select p.id, p.name, ph.personid...

我想你需要的是 -

select p.*, ph.personid 
  from person p
 Left join personhist ph on p.id = ph.personid
where (upper(p.name) = upper('oldtest') or upper(ph.name) like upper('oldtest'));

但我真的怀疑当你只需要显示时,加入的目的是什么只是第一个表。

答案 2 :(得分:0)

正如其他人所提到的那样(我不会打算),您可以通过在SELECT中指定实际需要的列来获取所需的数据,例如:

select p.name from person p
  Left join personhist ph on p.id = ph.personid
 where (upper(p.name) = upper('oldtest') or upper(ph.name) like upper('oldtest'));

但我想解决另一个问题。你为什么在这个例子中使用LIKE?没有任何通配符,因此您可以轻松使用=。此外,您可以执行以下操作:

SELECT p.name
  FROM person p LEFT JOIN personhist ph
    ON p.id = ph.personid
 WHERE 'OLDTEST' IN ( UPPER(p.name), UPPER(ph.name) );

如果您要搜索以OLDTEST开头的历史名称,那么您可能希望这样做:

SELECT p.name
  FROM person p LEFT JOIN personhist ph
    ON p.id = ph.personid
 WHERE ( UPPER(p.name) = UPPER('oldtest')
      OR UPPER(ph.name) LIKE UPPER('oldtest') || '%');

最后,确保您在PERSON上有一个基于函数的索引(也可能在PERSONHIST上有一个):

CREATE INDEX person_name_upper ON person ( UPPER(name) );