Oracle - 数学计算案例

时间:2011-02-24 15:58:46

标签: oracle count case

我正试图做一些动态计数,并希望有人可以帮助我在这里。知道如何使这项工作吗?

我想要做的是对列执行一些数学运算,然后计算符合条件的记录数。例如,我有这个数据

REPORT  bad_count   good_count
------------------------------
Y       30          20
Y       1           100

我想查看bad_count>> =总计数的20%的记录数...(坏+好)就像这样

REPORT  stuff
-------------
Y       1

这是我想到的查询,但收到错误。

select      REPORT,
            count(case round(bad_count / (good_count + bad_count) * 100) when >=20 then 1) as stuff
from        $A$
group by    REPORT

以下建议的答案

SELECT REPORT, COUNT(*) 
  FROM (SELECT REPORT, ROUND((bad_ct/(good_ct+bad_ct))*100) pct
         FROM $A$)
 WHERE pct >= 20
 GROUP BY REPORT;

但是,为什么在重写这样的时候它不起作用?

 SELECT         REPORT,
                count(case pct when >=20 then 1 end) as stuff
    FROM        (
                    SELECT  REPORT, 
                            ROUND((bad_ct/(good_ct+bad_ct))*100) pct
                    FROM    $A$
                )
    GROUP BY    REPORT

我更喜欢这样做的原因是我可能想要计算其他标准的实例。例如,我还想要一个新列'good_stuff',它是有多少记录也有good_ct非空的计数。

4 个答案:

答案 0 :(得分:1)

这样的事情:

SELECT REPORT, COUNT(*) 
  FROM (SELECT REPORT, ROUND((bad_ct/(good_ct+bad_ct))*100) pct
         FROM $A$)
 WHERE pct >= 20
 GROUP BY REPORT;

编辑:

我对这个问题的解释与其他响应者有点不同。我把问题看作是“行的数量(按REPORT字段分组),行的坏计数是> =行的总数。”

测试给出:

SQL> CREATE TABLE TEST (REPORT VARCHAR2(10), bad_count INTEGER, good_count INTEGER);

Table created
SQL> INSERT INTO TEST VALUES('Y',30,20);

1 row inserted
SQL> INSERT INTO TEST VALUES('Y',1,100);

1 row inserted
SQL> INSERT INTO TEST VALUES('Y',20,80);

1 row inserted
SQL> INSERT INTO TEST VALUES('Y',19,80);

1 row inserted

SQL> commit;

Commit complete

SQL> 
SQL> SELECT REPORT, COUNT(*) FROM (
  2  SELECT REPORT, ROUND((bad_count/(good_count+bad_count))*100) pct
  3    FROM TEST)
  4   WHERE pct >= 20
  5   GROUP BY REPORT;

REPORT       COUNT(*)
---------- ----------
Y                   2

SQL> 

答案 1 :(得分:0)

我相信你正在寻找

select      report,
            (case when round( total_bad/ (total_good + total_bad) * 100) >= 20
                  then 1
                  else 0
              end) stuff
from (
    select      REPORT,
                SUM(bad_count) total_bad,
                SUM(good_count) total_good
    from        $A$
    group by    REPORT
)

你应该能够在没有子查询的情况下通过将聚合放在CASE语句中来实现,但是这个表达式让我更容易理解。

答案 2 :(得分:0)

利用Oracle的分析功能:

SELECT REPORT, 1 stuff
FROM (
   SELECT REPORT,
          sum(good_count) over (partition by REPORT) total_good,
          sum(bad_count) over (partition by REPORT) total_bad
   FROM REPORT 
) WHERE round( total_bad / (total_good + total_bad) * 100) >= 20
ORDER BY REPORT;

答案 3 :(得分:0)

您正在尝试混合使用CASE的两种不同语法。

在一种语法中,CASE关键字紧跟第一个WHEN子句,每个WHEN子句都有一个完整的布尔表达式来评估,例如:

CASE WHEN pct >= 20 THEN ...

在另一种语法中,CASE关键字后面紧跟一个被计算的标量表达式;每个WHEN子句都有一个标量值,用于测试的相等性与第一个表达式的结果,例如:

CASE pct WHEN 20 THEN ...

您正在尝试使用第二种语法,但为WHEN子句赋予(部分)布尔表达式。你根本做不到。

我认为最好的解决方案是简单地使用第一种语法。即你在哪里写CASE pct WHEN >=20 THEN ...,而是写CASE WHEN pct>= 20 THEN ...。这很清楚,允许您制作任意复杂的CASE语句。

如果您真的喜欢使用第二种类似开关的语法,在某些情况下,您可以想出一种将所需测试转换为相等测试的方法。对于您的示例,您可以写:

CASE SIGN(pct-0.20) WHEN -1 THEN NULL ELSE 1 END

但对我而言,这似乎不像以另一种方式写作。