创建查询以获取未完成呼叫的计数

Create query to get count of uncompleted calls

有tablewaiter_log为

+---------+----------------+--------------+--------------+
| call_id | queue_num_curr | ast_num_curr | proceed_wait |
+---------+----------------+--------------+--------------+
| f27de4f | 9010           | 2            |            1 |
| f27de4f | 9002           | 5            |            1 |
| f27de4f | 9003           | 1            |            0 | 
| asdf231 | 9010           | 2            |            1 |
| asdf231 | 9002           | 5            |            1 |
| rete125 | 9010           | 2            |            1 |
| rete125 | 9009           | 5            |            1 |
| a7rf5gs | 9003           | 2            |            1 |
| a7rf5gs | 9006           | 5            |            1 |
| a7rf5gs | 9009           | 1            |            0 |
| qawe234 | 9003           | 2            |            1 |
| qawe234 | 9008           | 5            |            1 |
| qawe234 | 9004           | 1            |            0 |
| 49c43ad | 9004           | 2            |            1 |
| 49c43ad | 9007           | 5            |            1 |
+---------+----------------+--------------+--------------+

通话 ID 为 'f27de4f' 的通话开始于 9010 年,结束于 9003 年,因为对于通话 ID='f27de4f'
有一条 proceed_wait = 0 的记录 call-id 'asdf231' 的呼叫从 9010 开始,仍在 9002 继续并且尚未完成,因为没有 call-id='asdf231' 的 proceed_wait = 0 的记录 同样,对于呼叫 ID 'rete125' 的呼叫,没有 proceed_wait = 0 的记录,并且此呼叫也未完成。 所以,对于队列 9010 查询结果应该是 2(未完成呼叫的计数) 对于 9003,结果应为 0 ,因为对 9003('a7rf5gs' 和 'qawe234')的所有调用都已完成。 对于 9004,结果应为 1,因为对于呼叫 ID 为“49c43ad”的呼叫,没有 proceed_wait = 0 的记录。

如何创建查询以获取未完成呼叫的计数:

queue_num   count 
9010         2
9004         1

更新: 在这里我更新了我的问题

如果你是运行 MySQL 8.0,你可以用window函数来做到这一点:

select 
    min_queue_num_curr queue_num_curr,
    count(*) cnt
from (
    select 
        proceed_wait ,
        row_number() over(partition by call_id order by queue_num_curr desc) rn,
        min(queue_num_curr) over(partition by call_id) min_queue_num_curr
    from mytable
) t
where rn = 1 and proceed_wait = 1
group by min_queue_num_curr 

子查询检索每个call_id的起始queue_num_curr并对每个调用的记录进行排序。外部查询过滤最后一个记录 par 调用和未完成的调用,并通过开始 queue_num_curr.

进行聚合

Demo on DB Fiddle:

queue_num_curr | cnt
-------------: | --:
          9001 |   2
          9003 |   1
          9004 |   1

注意:调用 a7rf5gs 开始于 queue_num_curr = 9003 并在 queue_num_curr = 9009 上进行了 proceed_wait = 1,因此它也应该被视为未完成。


在早期版本中,您可以自行加入 table 以获取每个调用的开始 queue_num_cur,并使用相关子查询来过滤每个调用 ID 的最后一条记录。然后您可以过滤未完成的记录并通过开始 queue_num_cur:

进行聚合
select tmin.queue_num_curr, count(*)
from mytable t
inner join (
    select call_id, min(queue_num_curr) queue_num_curr from mytable group by call_id
) tmin on tmin.call_id = t.call_id
where 
    t.queue_num_curr = (
    select max(t1.queue_num_curr) from mytable t1 where t1.call_id = t.call_id
    )
    and t.proceed_wait = 1
group by tmin.queue_num_curr
order by tmin.queue_num_curr

Demo on DB Fiddle

如果我对逻辑的理解正确(对此我不确定),您可以 GROUP BY 队列和 count() 没有记录的不同呼叫 ID proceed_wait = 0存在,可以通过相关子查询查询。

SELECT wl1.queue_num_curr,
       count(DISTINCT
             (SELECT wl1.call_id
                     FROM dual
                     WHERE NOT EXISTS (SELECT *
                                              FROM waiter_log wl2
                                              WHERE wl2.call_id = wl1.call_id
                                                    AND wl2.proceed_wait = 0))) count
       FROM waiter_log wl1
       GROUP BY wl1.queue_num_curr;

如果 (call_id, queue_num_curr) 是唯一的,即没有呼叫在队列中出现超过一次,可以简化为只取 NOT EXISTSsum()(因为布尔值表达式在数字上下文中映射到 0(表示假)或 1(表示真)。

SELECT wl1.queue_num_curr,
       sum(NOT EXISTS (SELECT *
                              FROM waiter_log wl2
                                   WHERE wl2.call_id = wl1.call_id
                                         AND wl2.proceed_wait = 0)) count
       FROM waiter_log wl1
       GROUP BY wl1.queue_num_curr;

db<>fiddle

这是另一种无需相关子查询或 window 函数即可工作的方法:

对于每一行 w1,尝试找到具有相同 call_id 和 0 的另一行 w2,表示调用已完成。使用 LEFT OUTER JOIN,我们可以测试给定 call_id.

不存在 w2 行的情况

然后使用相同的 call_id 和较小的 ast_num_curr 值对假设的行 w3 进行另一个连接。同样,使用外连接,我们可以检查不存在这样的行。这意味着 w1 必须具有最小的 ast num 值 call_id。

SELECT w1.call_id, w1.queue_num_curr
FROM waiter_log AS w1
LEFT OUTER JOIN waiter_log AS w2
  ON w1.call_id = w2.call_id AND w2.proceed_wait = 0 
LEFT OUTER JOIN waiter_log AS w3
  ON w1.call_id = w3.call_id AND w1.ast_num_curr > w3.ast_num_curr
WHERE w2.call_id IS NULL AND w3.call_id IS NULL;

输出:

+---------+----------------+
| call_id | queue_num_curr |
+---------+----------------+
| 49c43ad |           9004 |
| asdf231 |           9010 |
| rete125 |           9010 |
+---------+----------------+

要获取每个 queue_num_curr 的计数,请将上面的查询包装在派生的 table 子查询中,并在外部查询中进行计数:

SELECT queue_num_curr, COUNT(*) AS count
FROM (
  SELECT w1.call_id, w1.queue_num_curr
  FROM waiter_log AS w1
  LEFT OUTER JOIN waiter_log AS w2
    ON w1.call_id = w2.call_id AND w2.proceed_wait = 0
  LEFT OUTER JOIN waiter_log AS w3
    ON w1.call_id = w3.call_id AND w1.ast_num_curr > w3.ast_num_curr
  WHERE w2.call_id IS NULL AND w3.call_id IS NULL
) AS t
GROUP BY queue_num_curr;

输出:

+----------------+-------+
| queue_num_curr | count |
+----------------+-------+
|           9004 |     1 |
|           9010 |     2 |
+----------------+-------+