PostgreSQL, що використовує count () для визначення відсотків (видати питання)


19

Я намагаюся запустити наступний запит, щоб вказати% рядків у моїй patientsтаблиці, які мають значення refinstстовпця. Я продовжую отримувати результат 0.

select (count (refinst) / (select count(*) from patients) * 100) as "Formula" 
from patients;

Таблиця містить 15556 рядків і select count(refinst) from patientsговорить мені, що 1446 з них мають значення у refinstстовпці. Відповідь, яку я хотів би отримати від запиту, була б 30,62 ( 1446/15556*100=30.62XXXXXокругленою до двох десяткових знаків).

Я впевнений, що це має щось спільне з типом даних результатів підрахунку (цілі числа, які я припускаю). Якщо я поділяю ціле число на ціле число, а результат менше 0, він обрізається на 0 правильним? Якщо це так, чи може хтось показати мені, як можна подати результати підрахунків як число з двома знаками після коми, щоб результат також був округлений до 2 десяткових знаків?

Я впевнений, що існує кращий спосіб написання цього коду, ніж заява з кількома підрахунками. Я шукаю більш ефективний процесор спосіб написання цього запиту, зокрема.


Можливо, ця відповідь може вам допомогти.
Jhon Anderson Cardenas Diaz

Відповіді:


26
SELECT (count(refinst) * 100)::numeric / count(*) AS refinst_percentage
FROM   patients;
  • Ви НЕ використовувати підзапит. Обидва агрегати можуть бути отримані з одного запиту. Дешевше.

  • Також це не стосується функцій вікон, оскільки ви хочете обчислити один результат, а не один результат у рядку.

  • Передайте будь-який числовий тип, який підтримує дробові цифри, як @a_horse вже пояснено .
    Оскільки ви хочете отримати round()дві дробові цифри, я пропоную numeric(що таке саме, як decimalу Postgres).
    Але достатньо віддати одне значення, яке бере участь у обчисленні, бажано перше. Postgres автоматично встановлюється для типу, який не втрачає інформацію.

  • Зазвичай це гарна ідея розмножуватись, перш ніж розділити . Зазвичай це мінімізує помилки округлення і дешевше.
    У цьому випадку перше множення ( count(refinst) * 100) можна обчислити дешевою і точною integerарифметикою. Тільки тоді ми кидаємо на numericта ділимо на наступне integer(що ми не кидаємо додатково).

Округлено до двох дробових цифр:

SELECT round((count(refinst) * 100)::numeric / count(*), 2) AS refinst_percentage
FROM   patients;

Звичайно, ти маєш рацію, функція вікна не потрібна. Але тоді це насправді не має значення (крім читабельності).
a_horse_with_no_name

3

Вам потрібно присвоїти кожне число, що бере участь у поділі, до типу, який підтримує десяткові знаки:

select (count(refinst)::decimal / (select count(*) from patients)::decimal) * 100  as "Formula" 
from patients;

Ви також можете спробувати функцію вікна замість скалярного підзапиту. Це може бути швидше:

select (count(refinst)::decimal / (count(*) over ())::decimal) * 100 as "Formula" 
from patients;

0

Я усвідомлюю, що цьому потоці є кілька років, але: спробуйте помножити на 100,0, а не на 100, що автоматично повинно передавати результат як плаваюче, а не ціле число.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.