Как я могу рассчитать проценты от общего количества строк и статуса в sql? - PullRequest
0 голосов
/ 06 мая 2020

У меня есть таблица со списком шаблонов и статусов, по которым я пытаюсь вычислить проценты.

Моя схема выглядит следующим образом:

Id autonumber
templateId text
personId Id
sentAt Date
status text

SQL SQL для создания БД

CREATE TABLE "test_db" ("id" integer,"templateId" text DEFAULT NULL,"personId" text DEFAULT NULL,"seenAt" text DEFAULT NULL,"status" text DEFAULT NULL, PRIMARY KEY (id));

Примеры данных:

| id | templateId | personId | seenAt              | status    |
+----+------------+----------+---------------------+-----------+
|  1 | test 1     | 123      | 17/01/2020 11:16:16 | delivered |
|  2 | test 1     | 456      |                     | rejected  |
|  3 | test 1     | 789      | 17/01/2020 11:16:16 | delivered |
|  4 | test 1     | 345      |                     | delivered |
|  5 | test 2     | 123      |                     | delivered |
|  6 | test 2     | 456      |                     | rejected  |
|  7 | test 2     | 789      | 17/01/2020 11:16:16 | delivered |

То, что я пытаюсь достичь:

| templateId | row_count | delivery_count | delivery_percentage | rejected_count | rejected_count |
+------------+-----------+----------------+---------------------+----------------+----------------+
| test 1     | 4         | 3              | 75%                 | 1              | 25%            |
| test 2     | 3         | 2              | 66.6%               | 1              | 33.3%          |

Запрос, который у меня есть до сих пор, следующее:

SELECT 
    *, (delivery_count / row_count * 100) AS delivery_percentage
FROM
    (SELECT 
         templateId, 
         COUNT(*) AS row_count,
         (SELECT COUNT(status)
          FROM test_db tb2  
          WHERE tb2.templateId = tb1.templateId AND status = 'delivered'
          GROUP BY tb2.templateId, status) AS delivery_count
      FROM 
          test_db tb1
      GROUP BY 
          templateId)

Проблема в том, что мои проценты ничего не возвращают атм, вы можете увидеть мой sqlfiddle здесь .

Кроме того, как вы можете видеть, у меня есть внутренние запросы для каждого статуса, поскольку количество статусов растет, я подозреваю, что запрос будет трудно читать / поддерживать, есть ли более эффективный способ сделать это?

1 Ответ

2 голосов
/ 06 мая 2020

Вы можете использовать условное агрегирование:

select templateId,
       sum(status = 'delivered') as num_delivered,
       avg(status = 'delivered') as ratio_delivered,
       sum(status = 'rejected') as num_rejected,
       avg(status = 'rejected') as ratio_rejected
from test_db
group by templateId;

В других базах данных вам может потребоваться более стандартный синтаксис:

select templateId,
       sum(case when status = 'delivered' then 1 else 0 end) as num_delivered,
       avg(case when status = 'delivered' then 1.0 else 0 end) as ratio_delivered,
       sum(case when status = 'rejected' then 1 else 0 end) as num_rejected,
       avg(case when status = 'rejected' then 1.0 else 0 end) as ratio_rejected
from test_db
group by templateId
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...