SQL, вычисляющий процент

#sql #subquery #aggregate-functions #percentage

#sql #подзапрос #агрегатные функции #процент

Вопрос:

Я пытаюсь получить процентное количество отклоненных утверждений (total_count / denied_count * 100) для поставщиков с менее чем 100 утверждениями. Я могу получить общее количество и отклоненное количество с помощью отдельных запросов, но у меня возникают проблемы с объединением всего вместе.

 SELECT
    PROVID,
    COUNT(CLAIMID) AS TOTAL_COUNT,
    COUNT(CLAIMID) / (SELECT COUNT(CLAIMID) * 100 
                      FROM #TEMPSTAGE 
                      WHERE STATUS = 'DENY') AS DENIED_PERCENTAGE
FROM 
    #TEMPSTAGE
WHERE 
    PROVID IN (SELECT DISTINCT PROVID
               FROM #TEMPSTAGE
               GROUP BY PROVID
               HAVING COUNT(CLAIMID) <= 100)
GROUP BY 
    PROVID
  

Пример результатов:

 ProvID / Total_Count / Denied Percentage
-----------------------------------------    
X12345  / 77       /     0
  

Я получаю нулевой процент отказа для всего, поскольку мой подзапрос в инструкции select не позволяет мне группировать по provid.

Ошибка

В списке выбора может быть указано только одно выражение, если подзапрос не введен с помощью EXISTS.

Каков наилучший способ сделать это??

Ответ №1:

Как и в большинстве языков, если вы выполняете 1 / 2 с целыми числами, результатом будет 0 , потому что для 0.5 нет целого числа. Чтобы получить десятичное число (фиксированная точка с плавающей запятой), вам необходимо преобразовать типы данных.

Как зависит от вашего диалекта SQL (MySQL, SQL Server, Oracle, PostgreSQL и т.д.).

 CAST(COUNT(CLAIMID) AS FLOAT)

CAST(COUNT(CLAIMID) AS DECIMAL(10, 4))

COUNT(CLAIMID) * 1.0

etc, etc
  

Далее, для использования IN список должен быть в фигурных скобках IN (1, 2, 3) , но для использования вложенного запроса запрос должен быть в фигурных скобках (SELECT x FROM y) .

Это означает, что для использования обоих вам нужны две пары фигурных скобок IN ((SELECT x FROM y))

Итак, наименьшие изменения в вашем запросе следующие…

 SELECT
    PROVID,
    COUNT(CLAIMID) AS TOTAL_COUNT,
    COUNT(CLAIMID) / (SELECT COUNT(CLAIMID) * 100.0
                      FROM #TEMPSTAGE
                      WHERESTATUS = 'DENY') AS DENIED_PERCENTAGE
FROM 
    #TEMPSTAGE
WHERE 
    PROVID IN ((SELECT PROVID
               FROM #TEMPSTAGE
               GROUP BY PROVID
               HAVING COUNT(CLAIMID) <= 100))
GROUP BY 
    PROVID
  

Тем не менее, подзапрос в предложении where может быть просто перемещен в основной запрос…

 SELECT
    PROVID,
    COUNT(CLAIMID) AS TOTAL_COUNT,
    COUNT(CLAIMID) / (SELECT COUNT(CLAIMID) * 100.0
                      FROM #TEMPSTAGE 
                      WHERE STATUS = 'DENY') AS DENIED_PERCENTAGE
FROM 
    #TEMPSTAGE
GROUP BY 
    PROVID
HAVING
    COUNT(CLAIMID) <= 100
  

Кроме того, я удалил DISTINCT ключевые слова. Если вы используете GROUP BY так, как вы есть, вам это не нужно.

ОТРЕДАКТИРОВАНО: Следующий комментарий

Вы можете пропустить подзапрос и просто просуммировать количество строк в группе, в которой находится статус 'DENY' .

Кроме того, процент (x * 100) / y не x / (y * 100) равен, поэтому я изменил вычисление на обратное.

 SELECT
    PROVID,
    COUNT(CLAIMID) AS TOTAL_COUNT,
    SUM(CASE WHEN STATUS = 'DENY' THEN 1 ELSE 0 END) * 100.0 / COUNT(CLAIMID) AS DENIED_PERCENTAGE
FROM 
    #TEMPSTAGE
GROUP BY 
    PROVID
HAVING
    COUNT(CLAIMID) <= 100
  

Комментарии:

1. @GregoryBrauninger Это не было четко указано в вашем вопросе. Ответ добавлен в

2. Ты потрясающий. Большое вам спасибо! Это беспокоило меня.