Oracle - 数学案例计数

发布于 2024-10-19 11:07:31 字数 1191 浏览 3 评论 0原文

我正在尝试做一些即时计数的案例,希望有人能在这里帮助我。知道如何进行这项工作吗?

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

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

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

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 的计数。

I'm trying to do some case counting on the fly and was hoping someone could help me out here. Any idea how to make this work?

What I want to do is perform some math on columns and then count the number of records that meet the criteria. So for example I have this data

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

I would want to see the count of records where the bad_count is >= 20% of the total count... (bad+good) like this

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

Here's the query I had in mind, but I receive an error.

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

This suggested answer from below worked

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

but, why does it not work when re-written like this?

 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

The reason I prefer to do it this way is I may want to count instance where there are other criteria as well. For example I also want a new column 'good_stuff' which is a count of how many records also had good_ct that isn't null.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

昔日梦未散 2024-10-26 11:07:31

像这样的事情:

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> 

Something like this:

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

EDIT:

My interpretation of the question was a bit different than the other responders. I took the question to be "what is the count of rows (grouped by the REPORT field) where the bad count for the row is >= to the total count for the row."

Testing gives:

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> 
ヅ她的身影、若隐若现 2024-10-26 11:07:31

我相信您正在寻找

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
)

You should be able to do it without the subquery by put theaggregate in the CASE statements 但这种表述让我觉得更容易遵循。

I believe you're looking for

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
)

You should be able to do it without the subquery by putting the aggregates in the CASE statement but this formulation strikes me as easier to follow.

白色秋天 2024-10-26 11:07:31

利用 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;

Take advantage of Oracle's analytics functions:

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;
尸血腥色 2024-10-26 11:07:31

您正在尝试混合两种不同的 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 语句。

如果您确实热衷于使用第二种类似 switch 的语法,那么在某些情况下您可以想出一种将所需的测试转换为相等测试的方法。对于你的例子,你可以写:

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

但这对我来说似乎不如以其他方式写清楚。

You are trying to mix the two distinct syntaxes of CASE.

In one syntax, the CASE keyword is immediately followed by the first WHEN clause, and each WHEN clause is given a full boolean expression to evaluate, e.g.:

CASE WHEN pct >= 20 THEN ...

In the other syntax, the CASE keyword is immediately followed by a scalar expression that is evaluated; each WHEN clause is given a scalar value to be tested for equality against the result of the first expression, e.g.:

CASE pct WHEN 20 THEN ...

You are trying to use the second syntax but give the WHEN clause a (partial) boolean expression. You simply can't do that.

I think the best solution is to simply use the first syntax. I.e. where you are writing CASE pct WHEN >=20 THEN ..., instead write CASE WHEN pct>= 20 THEN .... This is clear and allows you to make arbitrarily complex CASE statements.

If you are really attached to using the second, switch-like syntax, in some cases you can come up with a way of converting the test you want into an equality test. For your example, you could write:

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

But this seems less clear to me than writing it the other way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文