ORACLE SQL - 基于外键的查询

时间:2017-04-28 23:54:21

标签: sql oracle

下面是我需要进行查询的表的示例。

办公室表

       ---OFFICES----

OFFICE_ID - DEPARTMENT - EMPLOYEE_ID - MANAGER_ID

    1     - ACCOUNTING -    1      -      1 
    2     - ACCOUNTING -    2      -      2
    3     -     IT     -    3      -      3

员工表

     ---EMPLOYEES---

 EMPLOYEE_ID -  NAME - SURNAME

     1        - JOHN  - DOE
     2        - JOHN2 - DOE2
     3        - JOHN3 - DOE3

经理表

     ---MANAGERS---

MANAGER_ID - NAME   - SURNAME

    1     -  JOHN   - JONES
    2     -  GEORGE - GEORG
    3     -  ALEX   - JON

我想根据OFFICES表进行查询,并根据他们所在的部门对员工和经理进行分组,但我不确定如何。例如:

           ---QUERY RESULTS---

ACCOUNTING    -     IT

JOHN DOE         JOHN3 DOE
JOHN2 DOE        ALEX JON
JOHN JONES
GEORGE GEOGE

2 个答案:

答案 0 :(得分:1)

请尝试以下方法......

SELECT CASE accountingRowsFinder.name
           WHEN IS NULL THEN
               ''
           ELSE
               accountingRowsFinder.name
       END || ' ' || CASE accountingRowsFinder.surname
                         WHEN IS NULL THEN
                             ''
                         ELSE
                             accountingRowsFinder.surname
                     END AS Accounting,
       CASE ITRowsFinder.name
           WHEN IS NULL THEN
               ''
           ELSE
               ITRowsFinder.name
       END || ' ' || CASE ITRowsFinder.surname
                         WHEN IS NULL THEN
                             ''
                         ELSE
                             ITRowsFinder.surname
                     END AS IT
FROM ( SELECT rownum AS recordNumber,
              name AS name,
              surname AS surname,
              COUNT( * ) AS accountingCount
       FROM ( SELECT name,
                     surname
              FROM Employees
              JOIN Offices ON Employees.employee_id = Offices.employee_id
                          AND department = 'Accounting'
              UNION
              SELECT name,
                     surname
              FROM Managers
              JOIN Offices ON Managers.manager_id = Offices.manager_id
                          AND department = 'Accounting'
            ) accountingNamesFinder
     ) accountingRowsFinder
FULL JOIN ( SELECT rownum AS recordNumber,
                   name AS name,
                   surname AS surname,
                   COUNT( * ) AS ITCount
            FROM ( SELECT name,
                          surname
                   FROM Employees
                   JOIN Offices ON Employees.employee_id = Offices.employee_id
                               AND department = 'IT'
                   UNION
                   SELECT name,
                          surname
                   FROM Managers
                   JOIN Offices ON Managers.manager_id = Offices.manager_id
                               AND department = 'IT'
                 ) accountingNamesFinder
          ) ITRowsFinder ON accountingRowsFinder.recordNumber = ITRowsFinder.recordNumber

此语句为name中的每个surname选择EmployeeAccounting值,并使用{{1}将它们垂直连接到相应的Managers列表}}。然后,为此子查询中的记录分配记录号(也称为行号)和子查询中所有记录的计数,然后返回到语句的主体。

然后执行相同的过程以形成UNION department的类似列表。

然后基于{{1}的值,对从我们的子查询ITFULL JOIN获得的两个数据集执行FULL OUTER JOIN(也称为accountingRowsFinder) }}。对于那些没有相应条目的行,较长列表将为较短列表中的字段附加NULL值。

然后连接每个ITRowsFinder的已连接数据集中的名称字段。 recordNumber语句用于将department值替换为空字符串以用于显示和连接目的

如果您有任何问题或意见,请随时发表评论。

进一步阅读

http://docs.oracle.com/cd/B19306_01/server.102/b14200/expressions004.htmCASE

https://docs.oracle.com/cd/B19306_01/server.102/b14200/operators003.htm(在串联运算符NULL上)

https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm(加入时)

https://www.w3schools.com/sql/sql_join_full.asp(加入时)

答案 1 :(得分:1)

希望这会有所帮助。我正在使用这个版本 Oracle Database 11g企业版11.2.0.3.0版 - 64位生产

enter image description here

select regexp_substr(ACCOUNTING, '[^;]+', 1, level) ACCOUNTING,regexp_substr(IT, '[^;]+', 1, level) IT
    from (
with tmp as (
SELECT  (DECODE(department, 'ACCOUNTING', empname)) ACCOUNTING
        ,(DECODE(department, 'IT', empname)) IT
  FROM (
select distinct LISTAGG(empname, ';') WITHIN GROUP (ORDER BY department) over (partition by department)  empname,department from (
    select emp.name ||' '||emp.surname as empname
  ,ofc.department
  from EMPLOYEES emp
  ,Offices ofc
  where emp.EMPLOYEE_ID=ofc.EMPLOYEE_ID
  UNION
  select mgr.name||' '||mgr.surname as empname
  ,ofc.department
  from MANAGERS mgr
  ,Offices ofc
  where mgr.MANAGER_ID=ofc.MANAGER_ID 
  )
  ) 
  )
  select t1.accounting , t2.it
  from tmp t1, tmp t2
  where t1.accounting is not null
  and t2.it is not null
  )
connect by level <= length(regexp_replace(accounting, '[^;]+')) + 1;