【问题标题】:Oracle SQL - Query to calculate values from multiple tablesOracle SQL - 查询以计算来自多个表的值
【发布时间】:2018-02-10 18:25:04
【问题描述】:

我试图通过加入多个表从 sql 查询中获得所需的结果。由于本人知识有限,望大家帮忙。

我正在尝试获取每个经理和员工的审核详细信息。我有 3 张桌子:

1. HR
2. REQUIRED_AUDITS
3. SCORE_ENTRY

以下是HR表的示例数据:

+----+---------------+------------------+
| id | manager_email |        VP        |
+----+---------------+------------------+
|  1 | john@com.com  | jake@com.com     |
|  2 | smith@com.com | kathleen@com.com |
|  3 | maria@com.com | james@com.com    |
|  4 | linda@com.com | david@com.com    |
|  5 | jess@com.com  | kim@com.com      |
+----+---------------+------------------+

以下是 REQUIRED_AUDITS 表的示例数据:

+----+---------------+----------------+-----------------+----------------+
| ID | manager_email | employee_email | audits_required | audit_eligible |
+----+---------------+----------------+-----------------+----------------+
|  1 | john@com.com  | brad@com.com   |               5 | Y              |
|  2 | linda@com.com | gloria@com.com |               2 | Y              |
|  3 | linda@com.com | susan@com.com  |               7 | Y              |
|  4 | john@com.com  | carmen@com.com |               5 | Y              |
|  5 | linda@com.com | aaron@com.com  |              25 | N              |
+----+---------------+----------------+-----------------+----------------+

以下是 SCORE_ENTRY 表的示例数据:

+----+---------------+----------------+-------+
| ID | manager_email | employee_email | Score |
+----+---------------+----------------+-------+
|  1 | linda@com.com | gloria@com.com | 85.04 |
|  2 | linda@com.com | susan@com.com  |   100 |
|  3 | john@com.com  | carmen@com.com | 80.50 |
+----+---------------+----------------+-------+

所以现在我想显示每位经理所需的审核次数、完成的审核次数以及完成的百分比。

+-------------------------------+----------------------------------------------------------------------------+--------------------------------------------+-----------------------+
| Manager(list from "HR" table) | Total Audits Required(Sum of audits required from "REQUIRED_AUDITS table") | Audits Performed(from "SCORE_ENTRY" table) | Percentage Completion |
+-------------------------------+----------------------------------------------------------------------------+--------------------------------------------+-----------------------+
| john@com.com                  |                                                                         10 |                                          1 | 10%                   |
| linda@com.com                 |                                                                          9 |                                          2 | 22.22%                |
| smith@com.com                 |                                                                          - |                                          - | -                     |
| maria@com.com                 |                                                                          - |                                          - | -                     |
| jess@com.com                  |                                                                          - |                                          - | -                     |
+-------------------------------+----------------------------------------------------------------------------+--------------------------------------------+-----------------------+

计算如下:
1. 计算审核次数,即从 REQUIRED_AUDITS 表:
考虑经理 linda@com.com:
所需审核总数:7+3,因为只有两名员工符合条件
2. 完成的审计总数:
audits_required(来自 REQUIRED AUDITS 表)- 已完成审计(来自 SCORE_ENTRY 表)

如前所述,我对 sql 的了解有限,这对我来说看起来真的很复杂,因此在 Stack Overflow 中伸出援手。

感谢任何帮助。

更新 为了进一步简化流程,我编写了不包括 HR 表的离散查询,并且在组合以下查询时需要帮助。

查询1:我称之为“DENOMINATOR”

SELECT required_audits.manager_email, 
       SUM(audits_required) AS "TOTAL_AUDITS_REQUIRED" 
FROM   required_audits 
WHERE  Upper(required_audits.audit_eligible) = Upper('Y') 
GROUP  BY required_audits.manager_email 
ORDER  BY "total_audits_required" DESC 

+-------------------------------+-----------------------+
| required_audits.manager_email | TOTAL_AUDITS_REQUIRED |
+-------------------------------+-----------------------+
| john@com.com                  |                    10 |
| linda@com.com                 |                     9 |
+-------------------------------+-----------------------+

查询 2:我称之为 "NUMERATOR"

SELECT score_entry.manager_email, 
       Count(id) 
FROM   score_entry 
GROUP  BY score_entry.manager_email 

+---------------------------+-----------+
| score_entry.manager_email | Count(id) |
+---------------------------+-----------+
| john@com.com              |         1 |
| linda@com.com             |         2 |
+---------------------------+-----------+

在最终或结果中,我需要的只是 NUMERATOR**/**DENOMINATOR * 100 的百分比。我对连接和在 where 子句中应用条件感到困惑。

+---------------+-----------------------+------------------+-----------------------+
|    Manager    | Total Audits Required | Audits Performed | Percentage Completion |
+---------------+-----------------------+------------------+-----------------------+
| john@com.com  |                    10 |                1 | 10%                   |
| linda@com.com |                     9 |                2 | 22.22%                |
+---------------+-----------------------+------------------+-----------------------+

在结果表中,仅应显示审核合格的数字。这是出错的另一个原因。

提前致谢。

谢谢,
里查

【问题讨论】:

  • 您的原始结果集在 HR 表中显示 所有 个经理。您的第二个结果集仅显示 REQUIRED_AUDITS 表中有员工的经理。如果您不断更改要求,我们将无法提供解决方案。请编辑您的问题,使其始终保持一致。
  • @APC。感谢您的反馈。我试图用更简化的术语来解释相同的原始 OP。我不确定这会造成混乱。我考虑了您关于为什么要使用 HR 表的建议,因为我在技术上从 REQUIRED_AUDITS 表和 SCORE_ENTRY 表中收集信息。现在我想我确实需要 HR 表,因为它有更多的列,如名字、姓氏、电话号码等,所以觉得包含 HR 表会很好。为了简化数据,我没有包括这些列。如果我需要使用经理的名字,那么我将不得不加入 HR 表。再次抱歉。

标签: sql oracle


【解决方案1】:

您可以使用多个公用表表达式,分别计算每个表达式并将它们连接在一起 - 只是为了让您了解发生了什么。

SQL Fiddle

查询

WITH aud(manager_email,Total_audits) AS
  (SELECT manager_email,
    SUM (
    CASE
      WHEN audit_eligible = 'Y'
      THEN audits_required
    END )
  FROM REQUIRED_AUDITS
  GROUP BY manager_email
  ),  --Total_audits

  scores(manager_email,Audits_Performed) AS
  (SELECT manager_email,
    COUNT ( ID )
  FROM SCORE_ENTRY s
  GROUP BY manager_email
  )  --Audits_Performed

SELECT h.manager_email manager,
  a.Total_audits,
  s.Audits_Performed,
  100 * s.Audits_Performed / a.Total_audits percentage_complete
FROM HR h
LEFT OUTER JOIN aud a
ON h.manager_email = a.manager_email
LEFT OUTER JOIN scores s
ON h.manager_email = s.manager_email
ORDER BY 2 DESC NULLS LAST 

Results

|       MANAGER | TOTAL_AUDITS | AUDITS_PERFORMED | PERCENTAGE_COMPLETE |
|---------------|--------------|------------------|---------------------|
|  john@com.com |           10 |                1 |                  10 |
| linda@com.com |            9 |                2 |   22.22222222222222 |
| smith@com.com |       (null) |           (null) |              (null) |
|  jess@com.com |       (null) |           (null) |              (null) |
| maria@com.com |       (null) |           (null) |              (null) |

【讨论】:

  • 谢谢@Kaushik。这在 SQL Fiddle 中运行良好,但是当我在我的实例中运行时出现错误 ORA-32040:递归 WITH 子句必须使用 UNION ALL 操作。这些术语对我来说都是新的。对不起。
  • @Richa :不应该是这样,您使用的是哪个版本的 Oracle?也有可能在编辑时您修改了某些内容。
  • 谢谢@Kaushik。我正在使用 11gR2 版本。我可能在编辑时修改了一些内容。我的坏
  • 谢谢@Kaushik Nayak。 APC 提供的代码运行良好。我将再次尝试您的代码并让您知道。非常感谢您的帮助和时间。
  • 谢谢@Kaushik。即使在分数条目中添加多个相同的行后,此查询仍然有效。
【解决方案2】:

鉴于已发布的数据,无需在此查询中使用HR 表,因为manager_email 也在required_audits 表上。在现实生活中,使用像 manager_email 这样的列作为外国将是一个非常糟糕的主意。它应该是hr.id 列。

尽管如此,我还是将它包含在查询中,因为您要求这样做。

算术相当简单。复杂之处在于,您需要使用left outer join 到 HR 到 REQUIRED_AUDITS,因为并非所有经理都有需要审核的员工,并且还需要加入 SCORE_ENTRY,因为并非所有员工都经过审核。

select hr.manager_email
       , sum(ra.audits_required) as tot_audits_required
       , count(se.score) as audits_performed
       , (count(se.score) / sum(ra.audits_required)) * 100 as pct_complete      
from hr
left outer join ( select * from  REQUIRED_AUDITS 
                  where audit_eligible = 'Y') ra 
    on ra.manager_email = hr.manager_email
left outer join SCORE_ENTRY se 
    on se.employee_email = ra.employee_email
group by hr.manager_email
order by hr.manager_email
/

Oracle LiveSQL 上的演示。


“在结果表上,只有审核合格的数字才会显示。”

要实现此版本的要求,只需将 REQUIRED_AUDITS 上的 left outer join 转换为 inner join

【讨论】:

  • 感谢@APC。这真太了不起了。我尝试在“SCORE_ENTRY”表中添加一行数据,即不符合审计条件的 aaron@com.com。当我这样做时,在“TOT_AUDITS_REQUIRED”列下的最终输出中,经理 linda@com.com 的值是 34 而不是 9。您能否让我知道如何修改原始查询以将其合并?我使用 HR 表的原因是在 VP 级别显示详细信息以防万一。提前致谢。
  • 谢谢。我更改了更新问题中的表格数据,因为您建议不需要 HR 表格数据。我是按照你的建议去的。抱歉,如果它造成了混乱。我可能在编辑时做错了什么。
  • 谢谢,我完全理解。对不起所有的混乱。非常感谢您的时间和帮助
  • 我以冷静的心态尝试并花更多的时间来完成每一行查询。它就像一个魅力。我还在系统前端添加了验证,其中没有将不符合条件的员工添加到评分表中。感谢您的帮助和时间。我真的很感激。
  • 你能告诉我如何四舍五入百分比列吗?我尝试添加另一行 round((count(se.score) / sum(ra.audits_required)) * 100,2) 作为百分比 ** 和 **round((count(se.score) / sum(ra .audits_required)),2) 作为 other_method_percent 并且收到错误“ORA-00904:“RA”。“AUDITS_REQUIRED”:无效标识符”。谢谢
【解决方案3】:

假设从您上面的示例分数表中我们将查看得分行的数量而不是分数,这应该会有所帮助

select 
RA.manager_email, 
sum(RA.audits_requiered) as ReqQty,
(select count(manager_email) from SCORE_ENTRY as SE where SE.manager_email = RA.manager_email) as Compleated 

from REQUIRED_AUDITS as RA
group by manager_email
where audit_eligable='Y'

对于分数表,我不清楚这是否是您的意思。

【讨论】:

  • 感谢@Job Cluff。你是绝对正确的。它是得分行的数量而不是得分本身。当我执行代码时,出现错误 ORA-00907:缺少右括号。对我来说,它在视觉上看起来不错,但由于某种原因,我收到了这个错误。
  • select RA.manager_email, sum(RA.audits_requiered) as ReqQty, (select count(manager_email) from SCORE_ENTRY as SE where SE.manager_email = RA.manager_email) as Completed from REQUIRED_AUDITS as RA where audits_eligable= 'Y' group by manager_email
  • 在回答标记为[oracle] 的问题时,请务必使用有效的Oracle 语法,尤其是当OP 将自己标识为初学者时。 ORA-00907 错误是因为您的代码使用 as 作为对 Oracle 无效的表别名。
  • 对不起,我只是想帮忙
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多