如何使用外连接汇总行?

时间:2017-03-11 19:08:27

标签: sql oracle outer-join

问题:

我有以下表格,我想在两个字段中总结:HOURS和RATE。我还想从第三个表中检索NAME,加入LINE_NUM字段上的所有3个表。

如果LINE_NUM和CODE相同,则将A与B的字段相加。

Table EARNINGS A:

| EMPLOYEE_ID | LINE_NUM | REG_CODE | REG_HOURS | REG_RATE |
------------------------------------------------------------
| 0001        | 1        | C        | 20        | 200      |
| 0002        | 1        | H        | 0         | 0        |


Table OTH_EARNINGS B:

| LINE_NUM | OTH_CODE | OTH_HOURS | OTH_RATE |
----------------------------------------------
| 1        | A        | 0         | 0        |
| 1        | B        | 0         | 0        |
| 1        | C        | 10        | 100      |
| 2        | A        | 50        | 50       |


Table PAYCHECK C:

| EMPLOYEE_ID | LINE_NUM | NAME |
---------------------------------
| 0001        | 1        | Tom  |
| 0001        | 2        | Tom  |
| 0002        | 1        | John |

我要找的结果应该是:

| EMPLOYEE_ID | LINE_NUM | CODE | HOURS | RATE | NAME |
-------------------------------------------------------
| 0001        | 1        | A    | 0     | 0    | Tom  |
| 0001        | 1        | B    | 0     | 0    | Tom  |
| 0001        | 1        | C    | 30    | 300  | Tom  |
| 0001        | 2        | A    | 50    | 50   | Tom  |
| 0002        | 1        | H    | 0     | 0    | John |

知道如何实现这个目标吗?

我尝试了什么:

我已尝试(表A与C)UNION(表B与C),但我无法获得总和。

  SELECT C.EMPLOYEE_ID, A.REG_CODE, A.REG_HRS, SUM(A.REG_RATE) 
  FROM EARNINGS A, PAYCHECK C
  WHERE A.LINE_NUM = C.LINE_NUM
  GROUP BY C.EMPLOYEE_ID, A.REG_CODE, A.REG_HRS
UNION
  SELECT D.EMPLOYEE_ID, B.OTH_CODE, B.OTH_HRS, SUM(B.OTH_RATE) 
  FROM OTH_EARNINGS B, PAYCHECK D
  WHERE B.LINE_NUM = D.LINE_NUM
  GROUP BY D.EMPLOYEE_ID, B.OTH_CODE, B.OTH_HRS

但是我无法得到这笔钱并返回:

| EMPLOYEE_ID | LINE_NUM | CODE | HOURS | RATE | NAME |
-------------------------------------------------------
| 0001        | 1        | A    | 0     | 0    | Tom  |
| 0001        | 1        | B    | 0     | 0    | Tom  |
| 0001        | 1        | C    | 10    | 100  | Tom  |
| 0001        | 1        | C    | 20    | 200  | Tom  |
| 0001        | 2        | A    | 50    | 50   | Tom  |
| 0002        | 1        | H    | 0     | 0    | John |

1 个答案:

答案 0 :(得分:1)

你的方法并不糟糕,你几乎就在那里。

您应该对嵌套的2个UNIONed查询的结果进行GROUP BY:

SELECT EMPLOYEE_ID, NAME, CODE, SUM(HRS), SUM(RATE)
FROM
(  
      SELECT C.EMPLOYEE_ID, C.NAME, A.REG_CODE AS CODE, A.REG_HRS AS HRS, A.REG_RATE AS RATE
      FROM EARNINGS A
      INNER JOIN PAYCHECK C ON A.LINE_NUM = C.LINE_NUM

    UNION ALL

      SELECT D.EMPLOYEE_ID, C.NAME, B.OTH_CODE AS CODE, B.OTH_HRS AS HRS, B.OTH_RATE AS RATE
      FROM OTH_EARNINGS B 
      INNER JOIN PAYCHECK D ON  B.LINE_NUM = D.LINE_NUM
)  
GROUP BY EMPLOYEE_ID, NAME, CODE

然而,这将返回错误的结果,因为PAYCHECK表上的JOIN将返回重复项。

显然某处遗漏了某些东西。

要识别员工,您应该合并两列:EMPLOYEE_IDLINE_NUM。对于有关EARNING的第一个查询,由于表中存在EMPLOYEE_ID,因此没有问题。但是,对于OTH_EARNINGS上的第二个查询,EMPLOYEE_ID丢失了......

理论上你应该有这样的东西(检查INNER JOIN ...... ON)

SELECT EMPLOYEE_ID, NAME, CODE, SUM(HRS), SUM(RATE)
FROM
(  
      SELECT C.EMPLOYEE_ID, C.NAME, A.REG_CODE AS CODE, A.REG_HRS AS HRS, A.REG_RATE AS RATE
      FROM EARNINGS A
      INNER JOIN PAYCHECK C ON A.LINE_NUM = C.LINE_NUM AND A.EMPLOYEE_ID = C.EMPLOYEE_ID

    UNION ALL

      SELECT D.EMPLOYEE_ID, C.NAME, B.OTH_CODE AS CODE, B.OTH_HRS AS HRS, B.OTH_RATE AS RATE
      FROM OTH_EARNINGS B 
      INNER JOIN PAYCHECK D ON  B.LINE_NUM = D.LINE_NUM AND B.EMPLOYEE_ID = D.EMPLOYEE_ID
)  
GROUP BY EMPLOYEE_ID, NAME, CODE

我也从最初的查询中更改了:

  1. 从隐式到显式语法的JOIN。

  2. UNION成为UNION ALL,因为这里没有理由删除重复项(也许我错了)