【问题标题】:Oracle SQL newbie - Add new column that gets occurrence and computationsOracle SQL 新手 - 添加获取发生和计算的新列
【发布时间】:2018-02-20 04:44:31
【问题描述】:

这篇文章是我之前的帖子here的增强版。

请注意:这不是重复的帖子或线程。

我有 3 张桌子:

1. REQUIRED_AUDITS (Independent table)
2. SCORE_ENTRY (SCORE_ENTRY is One to Many relationship with ERROR table)
3. ERROR 

以下是虚拟数据和表结构:
REQUIRED_AUDITS TABLE

+-------+------+----------+---------------+-----------------+------------+----------------+---------+
|  ID   |  VP  | Director |    Manager    |    Employee     | Req_audits | Audit_eligible | Quarter |
+-------+------+----------+---------------+-----------------+------------+----------------+---------+
| 10001 | John | King     | susan@com.com | jake@com.com    |          2 | Y              | FY18Q1  |
| 10002 | John | King     | susan@com.com | beth@com.com    |          4 | Y              | FY18Q1  |
| 10003 | John | Maria    | tony@com.com  | david@com.com   |          6 | N              | FY18Q1  |
| 10004 | John | Maria    | adam@com.com  | william@com.com |          3 | Y              | FY18Q1  |
| 10005 | John | Smith    | alex@com.com  | rose@com.com    |          6 | Y              | FY18Q1  |
+-------+------+----------+---------------+-----------------+------------+----------------+---------+

SCORE_ENTRY TABLE

+----------------+------+----------+---------------+-----------------+-------+---------+
| SCORE_ENTRY_ID |  VP  | Director |    Manager    |    Employee     | Score | Quarter |
+----------------+------+----------+---------------+-----------------+-------+---------+
|              1 | John | King     | susan@com.com | jake@com.com    |   100 | FY18Q1  |
|              2 | John | King     | susan@com.com | jake@com.com    |    90 | FY18Q1  |
|              3 | John | King     | susan@com.com | beth@com.com    | 98.45 | FY18Q1  |
|              4 | John | King     | susan@com.com | beth@com.com    |    95 | FY18Q1  |
|              5 | John | King     | susan@com.com | beth@com.com    |   100 | FY18Q1  |
|              6 | John | King     | susan@com.com | beth@com.com    |   100 | FY18Q1  |
|              7 | John | Maria    | adam@com.com  | william@com.com |    99 | FY18Q1  |
|              8 | John | Maria    | adam@com.com  | william@com.com |  98.1 | FY18Q1  |
|              9 | John | Smith    | alex@com.com  | rose@com.com    |    96 | FY18Q1  |
|             10 | John | Smith    | alex@com.com  | rose@com.com    |   100 | FY18Q1  |
+----------------+------+----------+---------------+-----------------+-------+---------+

错误表

+----------+-----------------------------+----------------+
| ERROR_ID |            ERROR            | SCORE_ENTRY_ID |
+----------+-----------------------------+----------------+
|       10 | Words Missing               |              2 |
|       11 | Incorrect document attached |              2 |
|       12 | No results                  |              3 |
|       13 | Value incorrect             |              4 |
|       14 | Words Missing               |              4 |
|       15 | No files attached           |              4 |
|       16 | Document read error         |              7 |
|       17 | Garbage text                |              8 |
|       18 | No results                  |              8 |
|       19 | Value incorrect             |              9 |
|       20 | No files attached           |              9 |
+----------+-----------------------------+----------------+

我的查询给出以下输出:

+----------+---------------+------------------+------------------+------------------+
|          |               | Director Summary |                  |                  |
+----------+---------------+------------------+------------------+------------------+
| Director | Manager       | Audits Required  | Audits Performed | Percent Complete |
| King     | susan@com.com | 6                | 6                | 100%             |
| Maria    | adam@com.com  | 3                | 2                | 67%              |
| Smith    | alex@com.com  | 6                | 2                | 33%              |
+----------+---------------+------------------+------------------+------------------+

现在我想添加一列,我希望有错误的分数除以总分数

这不是错误总数除以得分数。相反,它对每次出现的错误计数并除以分数计数。
请查看以下示例:

考虑

导演:King
经理:susan@com.com

来自 SCORE_ENTRY TABLE 和 ERROR 表,

  • King 在 SCORE_ENTRY TABLE 中有 6 个条目
  • 错误表中有 6 个条目

我希望出现错误而不是 ERROR TABLE 中的 6 个条目,即 3 个错误。

计算质量的公式:
质量 = 1 -(错误发生的总和/总分)*100

对于国王: 质量 = 1 - (3/6)*100 质量 = 50

请注意:不是 1 - (6/6)*100

对于玛丽亚: 质量 = 1 - (2/2)*100 质量 = 0

下面是我需要的新输出,其中包含名为 Quality 的新列:

+----------+---------------+---------+------------------+------------------+------------------+
|          |               |         | Director Summary |                  |                  |
+----------+---------------+---------+------------------+------------------+------------------+
| Director | Manager       | Quality | Audits Required  | Audits Performed | Percent Complete |
| King     | susan@com.com | 50%     | 6                | 6                | 100%             |
| Maria    | adam@com.com  | 0%      | 3                | 2                | 67%              |
| Smith    | alex@com.com  | 50%     | 6                | 2                | 33%              |
+----------+---------------+---------+------------------+------------------+------------------+

下面是查询(感谢@Kaushik Nayak、@APC 和其他人)并且需要向该查询添加新列:

WITH aud(manager_email, director, quarter, total_audits_required) 
     AS (SELECT manager_email, 
                director, 
                quarter, 
                SUM (CASE 
                       WHEN audit_eligible = 'Y' THEN required_audits 
                     END) 
         FROM   required_audits 
         GROUP  BY manager_email, 
                   director, 
                   quarter), --Total_audits 
     scores(manager_email, director, quarter, audits_completed) 
     AS (SELECT manager_email, 
                director, 
                quarter, 
                Count (score) 
         FROM   oq_score_entry s 
         GROUP  BY manager_email, 
                   director, 
                   quarter) --Audits_Performed 
SELECT a.director, 
       a.manager_email manager, 
       a.total_audits_required, 
       s.audits_completed, 
       Round(( ( s.audits_completed ) / ( a.total_audits_required ) * 100 ), 2) 
                       percentage_complete, 
       a.quarter 
FROM   aud a 
       left outer join scores s 
                    ON a.manager_email = s.manager_email 
WHERE  ( :P4_MANAGER_EMAIL = a.manager_email 
          OR :P4_MANAGER_EMAIL IS NULL ) 
       AND ( :P4_DIRECTOR = a.director 
              OR :P4_DIRECTOR IS NULL ) 
       AND ( :P4_QUARTER = a.quarter 
              OR :P4_QUARTER IS NULL ) 
ORDER  BY a.total_audits_required DESC nulls last 

如果它令人困惑或需要更多详细信息,请告诉我。我愿意接受任何建议和反馈。

感谢任何帮助。

谢谢,
里查

【问题讨论】:

  • 你的问题很长,很多人会觉得很难理解。
  • 感谢@TimBiegeleisen。我确实解释了更多细节,因为这是我从之前的帖子中收到的反馈。简单来说,我只需要从上面的 3 个表中生成最终输出表。
  • 作为起点,您是否尝试过任何类似的方法;。在 SCORE_ENTRY_ID = entry_id 上的左外连接(select count(*), SCORE_ENTRY_ID from error_table group by SCORE_ENTRY_ID)
  • 嗨@LJ01 我确实尝试过单独或独立的查询,但我无法做到,因为它让我很困惑。我得到的输出为 1,但是当我对输出求和时,它给出了类似嵌套过多的错误。我不记得确切的错误。需要帮助找出适合 WITH 子句的查询,因为原始 WITH 子句工作正常。我也不知道如何在 WITH 子句中附加新查询。谢谢

标签: sql oracle count


【解决方案1】:

更新:
好吧,我的第一个猜测是错误的,我希望现在我猜对了。

根据你和shawnt00的cmets,你需要计算ERROR表中有对应条目的score条目的数量,并将其用于质量计算。
使用表达式得到的计数:

COUNT ((select max(1) from "ERROR" o where o.score_entry_id=s.score_entry_id)) AS error_occurences

max(1) 在“ERROR”中有条目时返回 1,否则返回 NULL。 COUNT 跳过空值。
我希望这很清楚。

质量计算为

(1 - error_occurences/audits_completed)*100%

以下是完整的脚本,其中 manager_email 重命名为 manager,oq_score_entry 重命名为 score_entry。 这符合你的方案。我还删除了不必要的 WITH 列映射,在这种情况下它只会使事情复杂化。

WITH aud AS (SELECT manager, director, quarter, SUM (CASE 
                   WHEN audit_eligible = 'Y' THEN req_audits 
                 END) total_audits_required 
     FROM   required_audits 
     GROUP  BY manager, director, quarter), --Total_audits 
 scores AS (
 SELECT manager, director, quarter, 
            Count (score) audits_completed,
            COUNT ((select max(1) from "ERROR" o where o.score_entry_id=s.score_entry_id)
                    ) error_occurences -- **  Added **
     FROM   score_entry s 
     GROUP  BY manager, director, quarter
               ) --Audits_Performed 
SELECT a.director, 
   a.manager manager, 
   a.total_audits_required, 
   s.audits_completed, 
   Round(( 1 - ( s.error_occurences ) / ( s.audits_completed )) * 100, 2), -- **  Added **
   Round(( ( s.audits_completed ) / ( a.total_audits_required ) * 100 ), 2) 
                   percentage_complete, 
   a.quarter 
FROM   aud a 
   left outer join scores s ON a.manager = s.manager 
WHERE  ( :P4_manager = a.manager 
      OR :P4_manager IS NULL ) 
   AND ( :P4_DIRECTOR = a.director 
          OR :P4_DIRECTOR IS NULL ) 
   AND ( :P4_QUARTER = a.quarter 
          OR :P4_QUARTER IS NULL ) 
ORDER  BY a.total_audits_required DESC nulls last 

关于total_errors

要添加此列,您可以使用类似于之前在 scores 中使用的技术:

scores AS (
    SELECT manager, director, quarter, 
           count (score) audits_completed,
           count ((select max(1) from "ERROR" o where o.score_entry_id=s.score_entry_id )
                   ) error_occurences,
           sum ( ( SELECT count(*) from "ERROR" o where o.score_entry_id=s.score_entry_id ) 
                   ) total_errors  -- summing error counts for matched score_entry_ids
    FROM   score_entry s 
    GROUP  BY manager, director, quarter
              )

或者您可以重写scores CTE 加入score_entryerror,这需要在score_entry 字段上使用DISTINCT 以避免行重复:

scores AS (
     SELECT manager, director, quarter, 
            count(DISTINCT s.score_entry_id) audits_completed,
            count(DISTINCT e.score_entry_id ) error_occurences, -- counting distinct score_entry_ids present in Error
            count(e.score_entry_id) total_errors -- counting total rows in Error
     FROM   score_entry s 
                LEFT JOIN "ERROR" e ON s.score_entry_id=e.score_entry_id
     GROUP  BY manager, director, quarter
               )

后一种方法维护性较差,因为它需要小心不必要的重复。

另一种(可能是最合适的)方法是制作一个单独的(第三个)CTE,但我认为查询不够复杂,不足以保证这样做。


原答案:
我可能是错的,但在我看来,通过“每次发生错误的计数”,您试图描述 COUNT(DISTINCT expr)。即计算每个(manager_email、director、 Quarter)的唯一错误发生次数。 如果是这样,请稍微更改查询:

WITH aud(manager_email, director, quarter, total_audits_required) 
 AS (SELECT manager_email, 
            director, 
            quarter, 
            SUM (CASE 
                   WHEN audit_eligible = 'Y' THEN required_audits 
                 END) 
     FROM   required_audits 
     GROUP  BY manager_email, 
               director, 
               quarter), --Total_audits 
 scores(manager_email, director, quarter, audits_completed, distinct_errors) 
 AS (SELECT manager_email, 
            director, 
            quarter, 
            Count (score),
            COUNT (DISTINCT o.error_id) -- **  Added **
     FROM   oq_score_entry s join error o on o.score_entry_id=s.score_entry_id 
     GROUP  BY manager_email, 
               director, 
               quarter) --Audits_Performed
SELECT a.director, 
   a.manager_email manager, 
   a.total_audits_required, 
   s.audits_completed, 
   Round(( ( s.distinct_errors ) / ( s.audits_completed ) * 100 ), 2) quality, -- **  Added **
   Round(( ( s.audits_completed ) / ( a.total_audits_required ) * 100 ), 2) 
                   percentage_complete, 
   a.quarter 
FROM   aud a 
   left outer join scores s 
                ON a.manager_email = s.manager_email 
WHERE  ( :P4_MANAGER_EMAIL = a.manager_email 
      OR :P4_MANAGER_EMAIL IS NULL ) 
   AND ( :P4_DIRECTOR = a.director 
          OR :P4_DIRECTOR IS NULL ) 
   AND ( :P4_QUARTER = a.quarter 
          OR :P4_QUARTER IS NULL ) 
ORDER  BY a.total_audits_required DESC nulls last 

【讨论】:

  • 谢谢@wolfrevokcats。我还没有尝试过这个查询,但我想说我想要一些与它们相关的错误的分数。这成为分子,总分成为本季度任何给定董事或经理的分母
  • @Richa,我已更新我的答案以符合您的说明。
  • 嗨@wolfrevokcats。我尝试了您提供的查询,它显示了 King 的 6 个错误而不是 3 个。它对重复的 score_entry_id 进行总计数而不是出现一次。
  • 嗨@wolfrevokcats。太棒了太棒了。太棒了..更新的查询就像一个魅力。你拯救了我的一天。你太有才华了。请让我知道如何像您一样学习和编写查询。你能告诉我任何我可以学习的书籍或材料吗
  • 谢谢@Richa,我很高兴能帮上忙。坦率地说,那个 sql 不需要任何天赋,唯一的障碍就是理解你需要什么。谈到书籍和资料,当我开始与 Oracle 合作时,几年来我只阅读官方文档,根本没有书籍。在你开始做正确的事情之前,有大量的 Oracle 文档需要阅读。如果您打算这样做,请三思而后行。
【解决方案2】:

一旦您有更多数据,主查询上的联接将需要包括主管和季度。

我认为解决此问题的最简单方法是遵循您已有的结构,并添加另一个表表达式,以与原始两个相同的方式将其连接到其余结果中。

select manager_email, director, quarter,
    100.0 - 100.0 * count (distinct e.score_entry_id) / count (*) as quality
from score_entry se left outer join error e
    on e.score_entry_id = se.score_entry_id
group by manager_email, director, quarter

让您的大部分解释变得不必要的是简单地说您想要与错误相关的分数的数量。从您提供的信息中很难得出这一点。

【讨论】:

  • 谢谢@shawnt00。你是绝对正确的。如果我说我想要一些与它们相关的错误的分数,那将是相当简单的。这就是我想要的。谢谢你纠正我。我从每个帖子中学到了很多东西。此外,我想让每个人都知道我尝试了什么以及哪里出错了。我会更新我的问题。谢谢。
  • 我不会像缺少信息那样抱怨额外的信息。在某些时候,尽管通读和过滤掉噪音变得太多工作。请记住,我们都没有得到报酬来提供帮助,因此我们希望您能尽最大努力让这件事变得尽可能简单。
  • 明白。我同意。再次感谢我正在更新问题
  • 嗨@shawnt00。我尝试了您提供的查询,它显示了 King 的 6 个错误而不是 3 个。它对重复的 score_entry_id 进行总计数而不是出现一次。
  • 不要计算 se.score_entry_id。确保它来自 e。
猜你喜欢
  • 1970-01-01
  • 2022-01-14
  • 2022-11-17
  • 2021-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多