如何在PostgreSQL中获得符合条件的行百分比?

时间:2017-08-25 09:57:30

标签: sql postgresql

嗨,我认为我有这张表

create table process(process_id serial, state text);
insert into process(process_id, state) values(1, 'DONE'),
                                          (2, 'DONE'),
                                          (3, 'DONE'),
                                          (4, 'FAILED');

现在如果您运行:

select distinct(state),count(*) a from process group by state;

你会得到两行:FAILED 1,DONE 3 我想要的是获得失败进程的百分比= FAILED /(FAILED + DONE)。

3 个答案:

答案 0 :(得分:2)

您可以使用case ... when。要避免整数除法,您还需要将其中一个数字转换为float:

select cast(count(case state when 'FAILED' then 1 end) as float) / count(*) a 
from process;

或者,您也可以使用nullif

select cast(count(nullif(state, 'DONE')) as float) / count(*) a 
from process;

答案 1 :(得分:2)

Postgres中的一种方法使用Dim ws As Worksheet Dim dataRng As Range Dim dic As Variant, arr As Variant Dim cnt As Long Set ws = Sheets("1") With ws lastrow = .Cells(.Rows.Count, "D").End(xlUp).Row 'get last row in Column D Set dataRng = .Range("D2:D" & lastrow) 'range for Column D Set dic = CreateObject("Scripting.Dictionary") arr = dataRng.Value For i = 1 To UBound(arr) dic(arr(i, 1)) = dic(arr(i, 1)) + 1 Next .Range("M2").Resize(dic.Count, 1) = Application.WorksheetFunction.Transpose(dic.keys) 'uniques data from Column D .Range("Q2").Resize(dic.Count, 1) = Application.WorksheetFunction.Transpose(dic.items) cnt = dic.Count For i = 2 To cnt + 1 .Range("N" & i & ":P" & i).Formula = "=SUMIF($D$2:$D$" & lastrow & ",$M" & i & ",E$2:E$" & lastrow & ")/" & dic(.Range("M" & i).Value) .Range("R" & i).Formula = "=IF(INDEX($I$2:$I$" & lastrow & ",MATCH($M" & i & ",$D$2:$D$" & lastrow & ",0))=0,N" & i & ","""")" .Range("S" & i).Formula = "=IF(INDEX($I$2:$I$" & lastrow & ",MATCH($M" & i & ",$D$2:$D$" & lastrow & ",0))=0,Q" & i & ","""")" .Range("T" & i).Formula = "=IF($S" & i & ">0,SUMPRODUCT(($D$2:$D$" & lastrow & "=$M" & i & ")*(($J$2:$J$" & lastrow & "-$E$2:$E$" & lastrow & ")>3%)),"""")" Next i .Range("M" & i).Value = "Grand Total" .Range("N" & i & ":P" & i).Formula = "=AVERAGE(N2:N" & cnt + 1 & ")" .Range("Q" & i).Formula = "=SUM(Q2:Q" & cnt + 1 & ")" .Range("R" & i).Formula = "=AVERAGE(R2:R" & cnt + 1 & ")" .Range("S" & i & ":T" & i).Formula = "=SUM(S2:S" & cnt + 1 & ")" .Range("N2:T" & .Cells(.Rows.Count, "M").End(xlUp).Row + 1).Value = .Range("N2:T" & .Cells(.Rows.Count, "M").End(xlUp).Row + 1).Value End With

avg()

如果您有其他状态,可以添加select avg( (state = 'FAILED')::int ) from process;

答案 2 :(得分:1)

使用FILTER缩小计算哪些行:

SELECT CAST(count(*) FILTER (WHERE state = 'FAILED') AS float)
       / count(*)
FROM process
WHERE state in ('FAILED', 'DONE');

有关详细信息,请参阅PostgreSQL文档中的Aggregate Expressions。第一个计数转换为float以防止在分割时出现整数截断。

FAILEDDONE中的状态过滤器是在WHERE子句而不是聚合过滤器中完成的,以确保state列上的任何索引都可以使用