Oracle 有一个包含活动周期的合同表,如何计算每日活动合同计数?
我有两张桌子:Oracle 有一个包含活动周期的合同表,如何计算每日活动合同计数?,oracle,optimization,common-table-expression,Oracle,Optimization,Common Table Expression,我有两张桌子: 合同(…,d1日期,d2日期,…)描述了一些合同并包含数百万(n*10^6!!!)行,d1和d2是相应的合同开始和终止日期 日历(d日期)包含连续日期列表(这样的表格对于不同的用途非常有用) 我需要为日历的每一行计算活动合同的数量,假设如果contract.d1你的方法很好,那么该合同是活动的,我认为没有更好的根本解决方案。 要想获得所有的合同交易,你必须至少考虑两次在合同表中的记录,你正在做。< /P> 一种微妙的不同的可能性是,不必对表进行双重扫描,而是执行一次扫描,并与
描述了一些合同并包含数百万(n*10^6!!!)行,合同(…,d1日期,d2日期,…)
和d1
是相应的合同开始和终止日期d2
包含连续日期列表(这样的表格对于不同的用途非常有用)日历(d日期)
我需要为
日历
的每一行计算活动合同的数量,假设如果contract.d1你的方法很好,那么该合同是活动的,我认为没有更好的根本解决方案。
要想获得所有的合同交易,你必须至少考虑两次在合同 表中的记录,你正在做。< /P>
一种微妙的不同的可能性是,不必对表进行双重扫描,而是执行一次扫描,并与包含激活和终止记录的两个记录表连接
with two as (
select 1 n from dual union all
select -1 n from dual),
contract_transactions as (
select
case when n = 1 then c.d1 else c.d2+1 end as d,
n
from contract c
cross join two d)
select d, sum(n) n
from contract_transactions
group by d
而不是您的双全表扫描
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1528K| 13M| 107K (1)| 00:25:06 |
| 1 | UNION-ALL | | | | | |
| 2 | HASH GROUP BY | | 764K| 6715K| 53785 (1)| 00:12:33 |
| 3 | TABLE ACCESS STORAGE FULL| CONTRACT | 764K| 6715K| 53767 (1)| 00:12:33 |
| 4 | HASH GROUP BY | | 764K| 6715K| 53785 (1)| 00:12:33 |
| 5 | TABLE ACCESS STORAGE FULL| CONTRACT | 764K| 6715K| 53767 (1)| 00:12:33 |
----------------------------------------------------------------------------------------
只有一次全表扫描
,但随后是两个记录表的联接
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1528K| 30M| 107K (1)| 00:25:07 |
| 1 | HASH GROUP BY | | 1528K| 30M| 107K (1)| 00:25:07 |
| 2 | MERGE JOIN CARTESIAN | | 1528K| 30M| 107K (1)| 00:25:06 |
| 3 | VIEW | | 2 | 6 | 4 (0)| 00:00:01 |
| 4 | UNION-ALL | | | | | |
| 5 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
| 6 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
| 7 | BUFFER SORT | | 764K| 13M| 107K (1)| 00:25:07 |
| 8 | TABLE ACCESS STORAGE FULL| CONTRACT | 764K| 13M| 53767 (1)| 00:12:33 |
-----------------------------------------------------------------------------------------
我不认为会有相关的性能差异(相同的选项是CBO;)
对我来说,使用联接将合同
记录拆分为两个事务更为自然。我测量了这些查询测试数据的时间,第一个面超过1秒,最后大约100ms。基本问题-1秒的时间真的不令人满意吗?多久执行一次此查询?每秒100次?每分钟一次?一天一次,或者一个月一次?是否值得花时间扩展此查询,并使其变得越来越复杂,以便客户端每天只进行一次查询,并且该查询将持续100毫秒而不是2秒?更复杂=将来更难维护。一些新的程序员在两年内将很难理解这个问题。在生产数据库上,这是几分钟vs 5秒,所以它确实值得改进。但要明确的是,没有人会运行这个查询,因为我开发它只是为了满足自己的好奇心;)谢谢你的想法,使用连接对我来说也更准确。
with
events_agg (d,n) as (
select d1, count(*) from contract group by d1 -- new contracts
union all
select d2+1, -count(*) from contract group by d2 -- term. contracts
),
counts_daily(d,n) as (
select d, sum(n)
from events_agg
group by d
),
counts_running(d,n) as (
select d, sum(n) over (order by d)
from counts_daily
order by d
)
select d,
nvl(n, lag(n ignore nulls) over(order by d)) n
from calendar
left join counts_running using(d)
order by d;
with
--- TEST DATA EMULATION ---
params as (
select trunc(sysdate) - 100 d0,
1e5 number_of_contracts,
100 max_contract_term
from dual
),
start_dates (d1) as(
select trunc(d0 + dbms_random.value(0, sysdate-d0)) d1
from params connect by level <= number_of_contracts
),
contract (d1, d2) as (
select d1,
trunc(d1 + dbms_random.value(0, max_contract_term)) d2
from start_dates, params
),
calendar (d) as (
select d0 + level - 1
from params
connect by level <= sysdate - d0 + 1
),
--- END OF TEST DATA ---
------------------------
...
with two as (
select 1 n from dual union all
select -1 n from dual),
contract_transactions as (
select
case when n = 1 then c.d1 else c.d2+1 end as d,
n
from contract c
cross join two d)
select d, sum(n) n
from contract_transactions
group by d
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1528K| 13M| 107K (1)| 00:25:06 |
| 1 | UNION-ALL | | | | | |
| 2 | HASH GROUP BY | | 764K| 6715K| 53785 (1)| 00:12:33 |
| 3 | TABLE ACCESS STORAGE FULL| CONTRACT | 764K| 6715K| 53767 (1)| 00:12:33 |
| 4 | HASH GROUP BY | | 764K| 6715K| 53785 (1)| 00:12:33 |
| 5 | TABLE ACCESS STORAGE FULL| CONTRACT | 764K| 6715K| 53767 (1)| 00:12:33 |
----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1528K| 30M| 107K (1)| 00:25:07 |
| 1 | HASH GROUP BY | | 1528K| 30M| 107K (1)| 00:25:07 |
| 2 | MERGE JOIN CARTESIAN | | 1528K| 30M| 107K (1)| 00:25:06 |
| 3 | VIEW | | 2 | 6 | 4 (0)| 00:00:01 |
| 4 | UNION-ALL | | | | | |
| 5 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
| 6 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
| 7 | BUFFER SORT | | 764K| 13M| 107K (1)| 00:25:07 |
| 8 | TABLE ACCESS STORAGE FULL| CONTRACT | 764K| 13M| 53767 (1)| 00:12:33 |
-----------------------------------------------------------------------------------------