计算每个月/每个月分组的门票的平均开放天数

问题描述 投票:0回答:1

我有以下(简化)表(Oracle DB):

id 创建于 已解决_at
1 2023-10-15 2023-10-29
2 2023-10-20
3 2023-11-01 2023-12-02
4 2023-11-15 2023-11-20
5 2023-12-03 2024-01-10
6 2024-01-04 2024-01-10

我想计算每月门票开放的天数。重要的是,开放门票将包含在开放的每个月的计算中。

从上面的例子来看,它将是:

2023-10:从工单 1 算起 4 天(解决时间 - 创建时间),从工单 2 算起 11 天(因为记录是开放的/整个月都没有解决)。所以平均开放天数为 (4 + 12) / 2 = 8

2023-11:从票证 2 起 30 天(因为它仍然开放)+ 从票证 3 起 30 天(也开放整个月)+ 从票证 4 起 5 天。平均开放天数为 65 / 3 = 21,6 天。

我对 SQL 并不陌生,但我从未遇到过类似的事情。理论上,可以从临时表/硬编码中选择我想要的月份并连接记录,但是没有更好的解决方案吗?

sql oracle
1个回答
0
投票

生成日历,然后外连接到日历并取该月内天数的平均值:

WITH calendar (month) AS (
  SELECT ADD_MONTHS(TRUNC(min_dt, 'MM'), LEVEL - 1)
  FROM   (
    SELECT MIN(created_at) AS min_dt,
           MAX(COALESCE(solved_at, SYSDATE)) AS max_dt
    FROM   table_name
  )
  CONNECT BY ADD_MONTHS(TRUNC(min_dt, 'MM'), LEVEL - 1) <= max_dt
)
SELECT TO_CHAR(c.month, 'YYYY-MM') AS month,
       AVG(
         LEAST(COALESCE(t.solved_at, TRUNC(SYSDATE)), ADD_MONTHS(c.month, 1))
         - GREATEST(t.created_at, c.month)
       ) AS avg_days
FROM   calendar c
       LEFT OUTER JOIN table_name t
       ON (c.month < COALESCE(t.solved_at, SYSDATE)
           AND t.created_at < ADD_MONTHS(c.month, 1))
GROUP BY
       c.month

对于样本数据:

create table table_name (id, created_at, solved_at) AS
SELECT 1, DATE '2023-10-15', DATE '2023-10-29' FROM DUAL UNION ALL
SELECT 2, DATE '2023-10-20', NULL FROM DUAL UNION ALL
SELECT 3, DATE '2023-11-01', DATE '2023-12-02' FROM DUAL UNION ALL
SELECT 4, DATE '2023-11-15', DATE '2023-11-20' FROM DUAL UNION ALL
SELECT 5, DATE '2023-12-03', DATE '2024-01-10' FROM DUAL UNION ALL
SELECT 6, DATE '2024-01-04', DATE '2024-01-10' FROM DUAL;

输出:

AVG_DAYS
2023-10 13
2023-11 21.66666666666666666666666666666666666667
2023-12 20.33333333333333333333333333333333333333
2024-01 15.33333333333333333333333333333333333333
2024-02 29
2024-03 31
2024-04 14

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.