Oracle - дело в математике - PullRequest
       16

Oracle - дело в математике

1 голос
/ 24 февраля 2011

Я пытаюсь сделать несколько подсчетов на лету и надеялся, что кто-нибудь может помочь мне здесь. Есть идеи, как заставить это работать?

То, что я хочу сделать, это выполнить некоторую математику для столбцов, а затем посчитать количество записей, которые соответствуют критериям. Так, например, у меня есть эти данные

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 ]

1 голос
/ 24 февраля 2011

Примерно так:

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

EDIT:

Моя интерпретация вопроса была несколько иной, чем у других респондентов. Я взял вопрос: «Каково количество строк (сгруппированных по полю ОТЧЕТ), где неправильное количество строк>> к общему количеству строк».

Тестирование дает:

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> 
0 голосов
/ 24 февраля 2011

Вы пытаетесь смешать два разных синтаксиса CASE.

В одном синтаксисе за ключевым словом CASE сразу следует первое предложение WHEN, и каждому предложению WHEN дается полное логическое выражение для оценки, например ::10000

CASE WHEN pct >= 20 THEN ...

В другом синтаксисе за ключевым словом CASE сразу следует скалярное выражение, которое оценивается; каждому предложению WHEN дается скалярное значение для проверки на равенство с результатом первого выражения, например ::10000

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

Но мне это кажется менее ясным, чем писать по-другому.

0 голосов
/ 24 февраля 2011

Воспользуйтесь преимуществами аналитических функций 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;
0 голосов
/ 24 февраля 2011

Я полагаю, что вы ищете

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, но эта формулировка кажется мне более легкой для понимания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...