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)
版本更易于创建和管理。