SQL - 如何使用嵌套连接

时间:2016-06-01 22:15:36

标签: 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 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条款中,但到目前为止我所做的尝试都没有完成

我非常感谢您提供的有关如何获得新表格的任何信息'从一个连接(例如我的第一个查询中的工作示例),然后只引用该表的剩余属性。第一个查询返回超过5,000个结果,而我的秒只返回2,500个。我需要第二个查询中的所有列,而不会牺牲从第一个查询返回的任何行。如果某些列的值为空,我不介意。

2 个答案:

答案 0 :(得分:0)

我开始更改为JOIN语法而不是所有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表。最顶尖的人怎么样?每个人都有主管吗?如果不是因为你可能有不同部门的不同经理,可能没有明确的主管。在这种情况下,这些人将不在列表中。要更正此问题,请将上面的JOIN更改为LEFT JOIN,这意味着如果没有基于联接的主管,则仍然包含PAAF记录,但是知道PAPF2值将返回null,但至少会返回它们。

同样适用于您的PHONE标准。您正在寻找明确的工作电话,但是如果有些人还没有提供工作电话条目呢?也让它成为LEFT JOIN。

因此,您可能希望将上面的所有JOIN更改为LEFT JOIN,并确保获得所有您想要的记录,而不考虑所有具有记录的相关表。

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

既然知道了这种情况,那么这些人是谁?要解决此问题,请将其更改回LEFT JOIN,并在WHERE子句中添加EXPECTING为NULL的条件。例如,关于主管的第一个例子。将查询更改为所有LEFT JOIN。然后,对于WHERE子句,添加以下内容...

AND papf2.person_id IS NULL

所以,这就是说,左连接给我所有记录,无论匹配。现在,从那时起,我只想要那些由于左连接而导致主管人员ID为空的记录,这意味着没有找到。因此,现在您可以看到所有没有主管的人,并确认或调整以适应这些人的适当主管身份。

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

AND pp.parent_id IS NULL

如果这个人有工作电话,我们不在乎。我们只想获得没有电话记录的人员名单。

希望这是有道理的......

答案 1 :(得分:-1)

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

  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问题的以下部分

  

我非常感谢您提供的有关如何从连接中获取新“表格”的信息(例如我的第一个查询中的工作示例),然后仅引用该表以获取其余属性。