Sql 是否可以在Oracle上创建计算列?

Sql 是否可以在Oracle上创建计算列?,sql,oracle,Sql,Oracle,我有一个表格,显示我的项目的每个步骤的统计信息。看起来是这样的: ITEM STEP_1 STEP_2 STEP_3 STEP_4 STEP_5 ----- -------- -------- -------- -------- -------- 1 OK NOK OK NOK IN ANALYSIS 2 OK OK OK OK

我有一个表格,显示我的项目的每个步骤的统计信息。看起来是这样的:

ITEM    STEP_1    STEP_2    STEP_3    STEP_4    STEP_5
-----  --------  --------  --------  --------  --------
1        OK        NOK        OK        NOK    IN ANALYSIS
2        OK        OK         OK        OK     N/A
3        NOK       NOK        NOK       NOK    NOK
我要做的是创建一个包含新进度列的视图。像这样:

ITEM    STEP_1    STEP_2    STEP_3    STEP_4    STEP_5       Progress
-----  --------  --------  --------  --------  --------     -----------
1        OK        NOK        OK        NOK    ANALYSIS        40%
2        OK        OK         OK        OK     N/A             100%
3        NOK       NOK        NOK       NOK    NOK              0%
百分比值的计算方法是:将每一个包含“OK”或“N/A”的步骤相加,然后除以步骤总数(在本例中为5)

有可能做到这一点吗

编辑1.:

像这样

ITEM    STEPs     STATUS 
-----  --------  --------
1       Step_1     OK
1       Step_2     NOK
1       Step_3     NOK
1       Step_4     ANALYSIS
1       Step_5     OK      
编辑:2:

下面是我如何进行规范化的简化版本:

SELECT

T.*

FROM
    ( SELECT DISTINCT
    ITEM_ID,

      (SELECT FINAL_STATUS
      FROM book_new b
      WHERE a.ITEM_ID        = b.ITEM_ID
      AND b.STEPS        = 'STEP_1'
      ) AS STEP_1 ,

      (SELECT FINAL_STATUS
      FROM book_new b
      WHERE a.ITEM_ID        = b.ITEM_ID
      AND b.STEPS        = 'STEP_2'
      ) AS STEP_2 ,

      (SELECT FINAL_STATUS
      FROM book_new b
      WHERE a.ITEM_ID        = b.ITEM_ID
      AND b.STEPS        = 'STEP_3'
      AND ROWNUM = 1
      ) AS STEP_3 ,

      (SELECT FINAL_STATUS
      FROM book_new b
      WHERE a.ITEM_ID        = b.ITEM_ID
      AND b.STEPS        = 'STEP_4'
      AND ROWNUM = 1
      ) AS STEP_4 ,

      (SELECT FINAL_STATUS
      FROM book_new b
      WHERE a.ITEM_ID        = b.ITEM_ID
      AND b.STEPS        = 'STEP_5'
      AND ROWNUM = 1
      ) AS STEP_5

FROM book_new A

    ) T

只需定义要使用的计算并包含别名:

CREATE OR REPLACE VIEW your_view AS
   SELECT item,
          step_1,
          step_2,
          step_3,
          step_4,
          step_5,
               (  CASE WHEN step_1 IN ('OK', 'N/A') THEN 1 ELSE 0 END
                + CASE WHEN step_2 IN ('OK', 'N/A') THEN 1 ELSE 0 END
                + CASE WHEN step_3 IN ('OK', 'N/A') THEN 1 ELSE 0 END
                + CASE WHEN step_4 IN ('OK', 'N/A') THEN 1 ELSE 0 END
                + CASE WHEN step_5 IN ('OK', 'N/A') THEN 1 ELSE 0 END)
             / 5
             * 100
          || '%'
             AS progress
   FROM   your_table
如果您希望根据
步骤
列的数量动态更改计算,那么您就倒霉了。RDBMS通常不用于处理动态列


此外,正如达菲莫所指出的,在适当规范化的设计中,这将非常容易。这还允许您动态调整步骤数。

如果您从非规范化数据开始,您可以通过分析计数查询找到每个项目的“确定”步骤百分比:

select item_id, steps, final_status,
  100 * count(case when final_status in ('OK', 'N/A') then final_status end)
    over (partition by item_id) -- analytic function with windowing clause
  / count(steps) over (partition by item_id) as percent_ok
from book_new
order by item_id, steps;

   ITEM_ID STEPS  FINAL_ST PERCENT_OK
---------- ------ -------- ----------
         1 STEP_1 OK               40
         1 STEP_2 NOK              40
         1 STEP_3 NOK              40
         1 STEP_4 ANALYSIS         40
         1 STEP_5 OK               40
         2 STEP_1 OK               100

...
然后,您可以将其转换为所需的表格格式;在11gR2或更高版本上,您可以使用内置的pivot操作符:

select item_id, a_step as step_1, b_step as step_2, c_step as step_3,
  d_step as step_4, e_step as step_5, percent_ok || '%' as progress
from (
  select item_id, steps, final_status,
    100 * count(case when final_status in ('OK', 'N/A') then final_status end)
      over (partition by item_id)
    / count(steps) over (partition by item_id) as percent_ok
  from book_new
)
pivot (max(final_status) as step for (steps) in ('STEP_1' as a, 'STEP_2' as b,
  'STEP_3' as c, 'STEP_4' as d, 'STEP_5' as e))
order by item_id;

   ITEM_ID STEP_1   STEP_2   STEP_3   STEP_4   STEP_5   PROGRESS                  
---------- -------- -------- -------- -------- -------- --------------------------
         1 OK       NOK      NOK      ANALYSIS OK       40%                       
         2 OK       OK       OK       OK       N/A      100%                       
         3 NOK      NOK      NOK      NOK      NOK      0%                        
在早期版本中,您可以使用聚合函数在事例表达式上手动透视数据:

select item_id,
  max(case when steps = 'STEP_1' then final_status end) as step_1,
  max(case when steps = 'STEP_2' then final_status end) as step_2,
  max(case when steps = 'STEP_3' then final_status end) as step_3,
  max(case when steps = 'STEP_4' then final_status end) as step_4,
  max(case when steps = 'STEP_5' then final_status end) as step_5,
  percent_ok || '%' as progress
from (
  select item_id, steps, final_status,
    100 * count(case when final_status in ('OK', 'N/A') then final_status end)
      over (partition by item_id)
    / count(steps) over (partition by item_id) as percent_ok
  from book_new
)
group by item_id, percent_ok
order by item_id;
这得到了相同的结果(这也是11g在引擎盖下所做的)

使用子查询的方法不会非常有效,因为要多次查询同一个表。但是,使用这种方法,您仍然可以使用@Allan的答案-只需更改外部
选择T.*FROM
即可列出列,并以相同的方式进行计算

您可以在文档中阅读有关和的更多信息


顺便说一句,您还可以稍微更改计算进度的方式。如果一个步骤为N/a,那么对其进行计数可能毫无意义;您可以将内部查询更改为忽略这些查询,只是为了计算:

  select item_id, steps, final_status,
    100 * count(case when final_status = 'OK' then final_status end)
      over (partition by item_id)
    / count(case when final_status != 'N/A' then final_status end)
      over (partition by item_id) as percent_ok
  from book_new

这对你的样本数据没有任何影响,但是如果你有一个项目是N/A,而其他项目是OK以外的,那么百分比就会上升。这可能不是您想要的,但它是一个选项…

这是一个非规范化设计。你应该考虑项目和步骤表之间的一对多关系。是的,这是可能的——即使是直截了当的,但如果数据是非正规化的话,这将是更容易的。您是否尝试过,如果是,您遇到了什么问题?在11g+中,您可以创建一个虚拟列。在早期版本中,您可以使用视图。对于这个新问题,我很抱歉,但你们所说的数据非规范化是什么意思?是不是有点像Edit1?Thx太多了!成功了!顺便说一句,我不知道枢轴功能。我可以用它来创建一个视图吗?是的,你可以;如果您确实有75个步骤,您可能会发现
max(case)
版本更易于创建和管理。