SQL-如何使用嵌套联接

SQL-如何使用嵌套联接,sql,oracle,join,Sql,Oracle,Join,我正在从服务器收集信息,但我编写的查询没有返回我要查找的所有值。如何使用不同类型的嵌套联接或查询来获取我要查找的所有数据 以下代码段返回我要查找的员工编号的总列表: select papf.employee_number, papf.full_name, paaf.person_id from per_all_people_f papf, per_all_assignments_F paaf where sysdate between papf.effective_start_date an

我正在从服务器收集信息,但我编写的查询没有返回我要查找的所有值。如何使用不同类型的嵌套联接或查询来获取我要查找的所有数据

以下代码段返回我要查找的员工编号的总列表:

select papf.employee_number, papf.full_name, paaf.person_id

from per_all_people_f papf, per_all_assignments_F paaf

where sysdate between papf.effective_start_date and papf.effective_end_date
and sysdate between paaf.effective_start_date and paaf.effective_end_date
and paaf.person_id > '0'
and papf.employee_number > '0'
and papf.person_id = paaf.person_id
order by 1;
不幸的是,下一个代码段在返回我想要的所有列时,并没有返回我以前从上述查询中获得的所有行:

select distinct loc.TOWN_OR_CITY city
       ,COALESCE(CASE WHEN (loc.location_code = 'Foo-Bar') THEN 'Foo-Bar' END, SUBSTR(loc.LOCATION_CODE, 1, INSTR(loc.LOCATION_CODE,'-','1','1')-1), loc.LOCATION_CODE) company
       ,loc.country
       ,papf.start_date created
       ,TRIM(SUBSTR(hou.name, INSTR(hou.name, '-','1','1')+1)) Department
       ,SUBSTR(pap.name, 1, INSTR(pap.name,'-','1','1')-1) Description 
       ,CONCAT(COALESCE(papf.known_as, papf.first_name), concat(' ', papf.last_name)) DisplayName
       ,hou.attribute5 Division
       ,papf.employee_number EmployeeNumber
       ,papf.first_name givenname
       ,papf2.full_name Manager
       ,CONCAT(COALESCE(papf.known_as, papf.first_name), concat(' ', papf.last_name)) name
       ,pp.phone_number OfficePhone
       ,papf.known_as OtherName
       ,loc.region_2 state
       ,loc.postal_code postalcode
       ,papf.last_name Surname
       ,pp.phone_number Telephone#
from   per_all_people_f   papf
       ,per_all_positions pap
       ,per_phones pp
       ,per_all_people_f   papf2
       ,per_all_assignments_f paaf
       ,hr_organization_units hou
       ,hr_locations_all loc
where
papf.person_id = paaf.person_id
and   papf2.person_id = paaf.supervisor_id
and   paaf.organization_id = hou.organization_id
and   loc.location_id = paaf.location_id
and sysdate between papf.effective_start_date and papf.effective_end_date
and sysdate between paaf.effective_start_date and paaf.effective_end_date
and sysdate between papf2.effective_start_date and papf2.effective_end_date
and pp.parent_id = papf.person_id
and phone_type = 'Work Phone'
and paaf.position_id = pap.position_id
;
从我读过的所有帖子中,我的印象是我需要做的工作都在From子句中,但迄今为止我所做的任何尝试都没有成功


如果您能提供关于如何从联接(如我第一次查询中的工作示例)中获取新“表”,然后仅为其余属性引用该表的任何信息,我将不胜感激。第一个查询返回的结果超过5000个,而我的第二个查询只返回2500个。我需要第二个查询中的所有列,而不牺牲第一个查询返回的任何行。我不介意某些列是否有空值。

看起来您可以在这里使用语法。这使您可以将子查询用作查询中的表。例如:

  with myj as
    (
    select papf.employee_number, papf.full_name, paaf.person_id

    from per_all_people_f papf, per_all_assignments_F paaf

    where sysdate between papf.effective_start_date and papf.effective_end_date
    and sysdate between paaf.effective_start_date and paaf.effective_end_date
    and paaf.person_id > '0'
    and papf.employee_number > '0'
    and papf.person_id = paaf.person_id
    )
  select --bunch of stuff
  from  myj
         ,anothertable atab
         ,yetanothertable yatab
  where
  myj.person_id = atab.col1 ... etc ...
编辑添加:以上只是为了解决OP问题的以下部分

如果您能提供关于如何从联接(如我第一次查询中的工作示例)中获取新“表”,然后仅为其余属性引用该表的任何信息,我将不胜感激


我首先改变了连接语法,而不是所有WHERE条件。 然后,猜测电话类型来自pp表别名

select distinct 
      loc.TOWN_OR_CITY city,
      COALESCE( CASE WHEN (loc.location_code = 'Foo-Bar') 
                     THEN 'Foo-Bar' END, 
                SUBSTR(loc.LOCATION_CODE, 1, INSTR(loc.LOCATION_CODE,'-','1','1')-1), 
                loc.LOCATION_CODE ) company,
      loc.country,
      papf.start_date created,
      TRIM(SUBSTR(hou.name, INSTR(hou.name, '-','1','1')+1)) Department,
      SUBSTR(pap.name, 1, INSTR(pap.name,'-','1','1')-1) Description,
      CONCAT( COALESCE(papf.known_as, papf.first_name), concat(' ', papf.last_name)) DisplayName,
      hou.attribute5 Division,
      papf.employee_number EmployeeNumber,
      papf.first_name givenname,
      papf2.full_name Manager,
      CONCAT(COALESCE(papf.known_as, papf.first_name), concat(' ', papf.last_name)) name,
      pp.phone_number OfficePhone,
      papf.known_as OtherName,
      loc.region_2 state,
      loc.postal_code postalcode,
      papf.last_name Surname,
      pp.phone_number Telephone#
   from
      per_all_people_f papf
         JOIN per_phones pp
            ON papf.person_id = pp.parent_id
           and pp.phone_type = 'Work Phone'         
         JOIN per_all_assignments_f paaf
            ON papf.person_id = paaf.person_id
           and sysdate between paaf.effective_start_date and paaf.effective_end_date
           JOIN per_all_people_f papf2
               ON paaf.supervisor_id = papf2.person_id 
              and sysdate between papf2.effective_start_date and papf2.effective_end_date
            JOIN hr_locations_all loc
               ON paaf.location_id = loc.location_id 
            JOIN hr_organization_units hou
               ON paaf.organization_id = hou.organization_id
            JOIN per_all_positions pap
               ON paaf.position_id = pap.position_id
   where
      sysdate between papf.effective_start_date and papf.effective_end_date
现在,你为什么会丢失记录?我只能提供这样一个事实:您加入的其他表可能有记录,也可能没有记录,这取决于它们的标准。我首先基于主管连接到PAPF2表。那头号人物呢。每个人都有主管吗?如果不是因为你可能有不同部门的不同经理,你可能没有明确的主管。在这种情况下,这些人将被排除在名单之外。若要更正此问题,请将上面的连接更改为LEFT JOIN(左连接),即如果没有基于该连接的管理器,则仍然包括PAAF记录,但要知道PAPF2值将返回null,但至少会返回

同样适用于您的手机标准。您正在明确查找工作电话,但如果有人尚未提供工作电话条目,该怎么办?把它也变成左连接

因此,您可能希望将上面的所有联接都更改为LEFT JOIN,并确保获得所需的所有记录,而不考虑所有相关表是否有记录

然后,一次一个连接将其从左连接更改回连接,并查看有多少记录从结果集中删除。这将告诉您某些记录没有匹配项

既然你知道了,这些人是谁?要解决此问题,请将其更改回左联接,并在WHERE子句中添加一个预期为NULL的条件。例如,第一个关于主管的例子。将查询更改为all LEFT JOIN。然后,对于WHERE子句,添加以下内容

AND papf2.person_id IS NULL
所以,这是说,左联合给我所有的记录,不管匹配。现在,从这一点出发,我只想要那些由于左连接而导致主管的个人ID为NULL的记录,这意味着找不到。因此,现在您可以看到所有没有主管的人,并确认或调整以对这些人应用适当的主管状态

然后,再次尝试手机。。。删除上面的第一个AND子句,然后添加

AND pp.parent_id IS NULL
如果对方有工作电话,我们不在乎。我们只想得到没有电话记录的人的名单


希望这是有意义的…

据我所知,您有一些人丢失了电话号码或位置等,也许去一些外部连接会有所帮助?我建议您尝试逐个删除添加到查询中的新表,并查看哪个表连接失败您的第二个查询具有更多筛选器/限制,因此它们得到不同的结果也就不足为奇了。也许你在寻找外部连接?您应该认真考虑使用ANSI连接语法,而不是使用这种非常古老的结构来分离连接和筛选条件——特别是如果您想要外部联接。您需要使用外部连接来获得所需的数据。但首先需要重写以使用ANSI连接内部连接语法,因为使用现有的旧式语法编写外部连接*=容易出错且不明确。我建议您也一个接一个地删除每个附加表,以确定哪一个表需要再次进行外部联接例如,如果第一个查询的ANSI语法是从papf.person\u id=paaf.person\u idYour上的per\u all\u PEOPEN\f papf内部联接per\u all\u分配\u f paaf无法解析记录为m的原因
是的,它只是简化了一个可读性查询的一部分。你是对的,它只是回答了问题的这一部分。我非常感谢你能提供任何信息,说明如何从联接中获得一个新的“表”,比如我第一次查询中的工作示例,然后只引用该表中的其余属性。我应该说得很清楚。不久的将来,当我获得15%的声誉时,我会在这个回答上猛击一支向上的箭。非常感谢您对代码和理论示例的清晰而简单的解释;这是我唯一希望得到的高质量答案。@ThaddeusRix,如果此解决方案有效,单击答案旁边的复选框表示已解决。另外,请查看帮助->浏览,了解其他问题和网站礼仪。欢迎来到S/O。复选标记是你的。再次感谢您给出的令人难以置信的答案,以及您在解释如何实现解决方案方面付出的巨大努力。在papf2和pp上添加左连接完成了这项工作。现在我需要更新大约2500条记录来删除那些空列。