【问题标题】:Selection with left join but without showing the Data inside the joined table选择左连接但不显示连接表内的数据
【发布时间】:2015-01-29 11:09:10
【问题描述】:

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

这样的餐桌人:

id name etc.   
1  test   
2  smith  
3  shaw

还有第二个表格 personhist,我在其中记录了姓名的更改,如下所示:因此,如果有人因为结婚或类似原因更改了姓名,我仍然使用旧名。

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

但我只想得到实际的名称结果。所以问题是:如果我加入的表中有记录,有没有办法只显示“主”表中的数据?

【问题讨论】:

  • 我的第一个想法是'不要使用select *',但我不太确定你想看到什么——只是p.name 值?那为什么要加入呢?也许您可以展示您的预期结果,以及一些更多样化的数据?
  • @AlexPoole 我想从人那里看到一切,但如果我用旧名称搜索,我想看到新名称

标签: sql oracle select join left-join


【解决方案1】:
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'))

【讨论】:

  • 为什么要合并?这个名字无论如何都会被重复。要求是只显示一个名称列,在您的查询中由p.* 给出,现在合并将添加另一个实际上应该排除的名称列。
【解决方案2】:

但我只想得到实际名称结果。所以问题是如果我加入的表中有记录,有没有办法只显示“主”表中的数据?

不要包含您不想显示的列。您正在使用 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'));

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

【讨论】:

    【解决方案3】:

    正如其他人所提到的(我不会堆积),您可以通过在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) );
    

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 2018-10-05
      • 2013-01-30
      • 2022-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多