Получение отсчетов на основе статуса рельсов записи - PullRequest
0 голосов
/ 13 марта 2019

У меня есть сценарий, в котором я должен показать количество всех зарегистрированных людей для процесса. Есть два состояния в процессе и завершены. Человек может зарегистрировать процесс несколько раз, и каждый раз мы отслеживаем человека в таблице с именем process_people. Каждый процесс, который записывают люди, может быть на разных этапах процесса.

Допустим, человек А входит в процесс А и завершил процесс, а тот же человек снова входит и становится частью процесса (в процессе).

Что мне нужно, так это то, что мне нужно, чтобы получить уникальное общее количество зарегистрированных людей, я могу получить это, используя приведенное ниже,

unique_count = ProcessPerson.where(status: %[completed inprogress]).select(:person_id).distinct.count

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

Всего зачисленных людей = уникальных (находящихся в процессе работы + завершенных людей)

Активные люди = уникальные (кто находится в процессе и не завершил тот же процесс раньше)

Может кто-нибудь помочь мне с этим?

Ответы [ 2 ]

1 голос
/ 13 марта 2019

Вы можете попробовать этот запрос:

SELECT grouped_process_people.* 
FROM (
  SELECT ordered_process_people.* 
  FROM (
    SELECT process_id, people_id, status 
    FROM scratch.process_people 
    ORDER BY (status = 'completed') DESC , status /* (1) */
    ) as ordered_process_people 
  GROUP BY process_id, people_id /* (2) */
) as grouped_process_people 
WHERE status <> 'completed'; /* (3) */

Что происходит в этом SQL (используйте числа рядом с подзапросами), скажем, ваша таблица выглядит следующим образом:

+----+------------+-----------+------------+
| id | process_id | people_id |   status   |
+----+------------+-----------+------------+
|  1 |         11 |        21 | inprogress |
|  2 |         11 |        21 | completed  |
|  3 |         11 |        21 | inprogress |
|  4 |         12 |        21 | inprogress |
|  5 |         12 |        21 | inprogress |
|  6 |         12 |        21 | inprogress |
|  7 |         13 |        23 | inprogress |
|  8 |         13 |        23 | completed  |
+----+------------+-----------+------------+
  1. Упорядочить таблицу так, чтобы строки с завершенным статусом находились сверху.
+------------+-----------+------------+
| process_id | people_id | status     |
+------------+-----------+------------+
|         11 |        21 | completed  |
|         13 |        23 | completed  |
|         11 |        21 | inprogress |
|         11 |        21 | inprogress |
|         12 |        21 | inprogress |
|         12 |        21 | inprogress |
|         12 |        21 | inprogress |
|         13 |        23 | inprogress |
+------------+-----------+------------+
Сгруппируйте по process_id и people_id, чтобы была выбрана только уникальная комбинация этих пар, причем те, которые имеют статус завершенной, помечены так.
+------------+-----------+------------+
| process_id | people_id | status     |
+------------+-----------+------------+
|         11 |        21 | completed  |
|         12 |        21 | inprogress |
|         13 |        23 | completed  |
+------------+-----------+------------+
Теперь, поскольку мы хотим, чтобы только те, которые не были выполнены, третий и самый внешний запрос отфильтровали бы те, которые имеют статус завершенных.
+------------+-----------+------------+
| process_id | people_id | status     |
+------------+-----------+------------+
|         12 |        21 | inprogress |
+------------+-----------+------------+

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

ProcessPerson.find_by_sql(active_people_process_query)
0 голосов
/ 14 марта 2019

Я не думаю, что это можно сделать за один шаг (один запрос), но я думаю:

  • Сначала мы группируем по person_id & process_id

    step_1 = ProcessPerson.all.select(:person_id, :process_id, :status).group_by{ |pp| [pp.person_id, pp.process_id]}
    

    Результат:

    {
      [5, 5]=> [
        {person_id: 5, process_id: 5, status: "completed"},
        {person_id: 5, process_id: 5, status: "inprogress"}
      ],
      [4, 1]=>[
        {person_id: 4, process_id: 1, status: "completed"},
        {person_id: 4, process_id: 1, status: "inprogress"}
      ],
      [6, 5]=>[
        {person_id: 6, process_id: 5, status: "completed"}
      ],
      [2, 5]=>[
        {person_id: 2, process_id: 5, status: "completed"}
      ],
      [6, 2]=>[
        {person_id: 6, process_id: 2, status: "inprogress"}
      ],
      [2, 2]=>[
        {person_id: 2, process_id: 2, status: "completed"}
      ],
      [5, 3]=>[
        {person_id: 5, process_id: 3, status: "inprogress"}
      ],
      [3, 4]=>[
        {person_id: 3, process_id: 4, status: "completed"}
      ]
    }
    
  • Затем мы выбираем любые группы, которые находятся в процессе и не завершили процесс

    step_2 = step_1.filter{ |k, v| v.any? {|h| h[:status] == "inprogress" } && !v.any? {|h| h[:status] == "completed" } }      
    

    Результат:

    {
      [6, 2]=>[
        {person_id: 6, process_id: 2, status: "inprogress"}
      ],
      [5, 3]=>[
        {person_id: 5, process_id: 3, status: "inprogress"}
      ]
    }
    
  • Затем мы считаем результат

    step_3 = step_2.count
    

    Результат:

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