根据记录轨道的状态获取计数

时间:2019-03-13 17:56:14

标签: ruby-on-rails activerecord ruby-on-rails-5 unique

我有一个场景,我必须显示某个流程的总注册人数。有两种状态,正在进行和完成。该人员可以多次注册该流程,并且每次我们在名为process_people的表中跟踪该人员。人们记录的每个流程可能处于流程的不同步骤。

假设某人A进入过程A并完成了该过程,而同一个人再次进入并成为该过程的一部分(进行中)。

我需要获得唯一的总注册人数,我可以使用以下方法获得该数字,

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

要求是显示唯一的活跃人数,这也应该是唯一的人数。如果一个人完成了相同的过程并且在同一过程中进行了进度,则意味着我们需要在活跃人员计数中跳过它们。正在进行的过程且之前未完成同一过程的人数是预期结果。

注册总人数=唯一(进步中的人+已完成的人)

活跃的人=独特的(谁在进行中并且之前未完成相同的过程)

有人可以帮我吗?

2 个答案:

答案 0 :(得分:1)

您可以尝试以下查询:

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 |
+------------+-----------+------------+
  1. process_idpeople_id分组,以便仅选择这些对的唯一组合,并标记状态为已完成的对。
+------------+-----------+------------+
| process_id | people_id | status     |
+------------+-----------+------------+
|         11 |        21 | completed  |
|         12 |        21 | inprogress |
|         13 |        23 | completed  |
+------------+-----------+------------+
  1. 现在,由于我们只希望未完成的查询,因此第三个也是最外面的查询将过滤出状态为已完成的查询。
+------------+-----------+------------+
| process_id | people_id | status     |
+------------+-----------+------------+
|         12 |        21 | inprogress |
+------------+-----------+------------+

运行此查询的方式是将其存储为字符串,例如,如果将其存储在名为active_people_process_query的变量中,则它将像这样运行:

ProcessPerson.find_by_sql(active_people_process_query)

答案 1 :(得分:0)

我认为这不能一步完成(一个查询),但是我的想法是:

  • 首先,我们按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