问题描述
我正在尝试创建一个查询,该查询对一年内存在的记录进行计数。该表如下所示:
Title_ID ISSUE_DATE EXPIRY_DATE CLIENT_NUMBER
123 '26-JUN-19' '17-AUG-20' 8529
124 '04-APR-19' '17-SEP-22' 8529
125 '09-MAY-15' '11-SEP-19' 3654
126 '31-DEC-19' '25-NOV-22' 9852
127 '27-OCT-18' '26-FEB-21' 2254
128 '05-OCT-11' '01-JAN-19' 9852
具体地说,我想计算给定日历年中存在的不同CLIENT_NUMBERS条记录。
记录(标题)从ISSUE_DATE到EXPIRY_DATE一直存在。如果该记录在一年中的某个时间点存在(比如说2019年),那么我们有兴趣将其包括在客户数量中。
因此,如果记录在2019年发布或,或者如果记录在2019年过期或,如果记录在2019年之前发布且在2019年之后过期,那么我们很感兴趣将其计入其存在的年份的客户计数中。
我建立了以下查询来执行此操作,但仅针对特定的一年(2019年)。我想进一步构建查询,以便在客户拥有有效标题时查看每个日历年并计算不同的客户编号:
SELECT *
-- count(distinct client_number)
FROM
TITLE
WHERE
issue_date between '01-Jan-19' and '31-Dec-19'
or expiry_date between '01-Jan-19' and '31-Dec-19'
or (issue_date < '01-Jan-19' and expiry_date > '31-Dec-19')
我遇到麻烦的地方,我的数据比我提供的子集大得多。我想使用相同的逻辑,按年递归地获得不同客户数量的计数,以包括我上面概述的日历年内的记录。所以,我想要一张这样的桌子:
YEAR COUNT_OF_CLIENT_NUMBERS
2020 5469
2019 5587
2018 4852
2017 4501
2016 3265
etc
我认为目前我已经对当前的sql功能感到困惑,所以我想问一下是否有任何建议可以实现这一目标?
谢谢。
编辑:为澄清起见,发布日期和有效期适用于标题,而不适用于客户。因此,标题在发布日期发布,并在到期日期过期。客户可以拥有一个或多个标题。
因此,我希望统计一个特定年度内,如果一个或多个客户处于活跃状态,那么有多少不同的客户拥有该年度的活跃标题。因此,关键是,如果一个标题是在该年份 OR 发布的,并且在该年之前发布的,而在该年份之前发布的,并且在该年之后过期的,则该标题被认为是有效的。标题可以可以使用多年(例如,于2014年2月4日发布,于2017年4月7日到期),我想列出存在该标题的每一年的客户数量.... 2014 ,2015、2016和2017年)。
因此,我创建了一个要联接的表(感谢@GMB的建议):
with calendar_year (y) as
(
select 2010 from dual
union all select y + 1 from calendar_year where y < 2020
)
select * from calendar_year
哪个返回:
2010
2011
2012
2013
2014
etc
我想将其加入到标题表中,但是在递归查看发布日期和有效期以将标题合并到其存在的年限时,我遇到了一些问题。在该领域的任何帮助都将非常棒! / p>
解决方法
通过取消数据透视表,您可以在任何一天获得客户数量,因此每个日期只有一行。然后跟踪“进”和“出”。
您没有指定数据库,但这是一种方法:
select dte,sum(inc),sum(sum(inc)) over (order by dte) as active_on_date
from ((select issue_date as dte,1 as inc
from t
) union all
(select expiry_date as dte,-1 as inc
from t
)
) t
group by dte
order by dte;
编辑:
嗯,以上内容可能无法完全满足您的要求。如果您要计算与众不同的客户编号而不是总行数,则只列出日期和join
可能会更简单:
select d.dte,count(distinct t.client_id)
from (select date '2020-01-01' as dte from dual union all
select date '2019-01-01' as dte from dual union all
select date '2018-01-01' as dte from dual union all
. . .
) d left join
t
on d.dte between t.issue_dte and t.expiry_dte
group by d.dte
order by d.dte;
,
您可以使用递归查询生成年份,然后通过左连接将表带进去并进行汇总:
with dates (dt) as (
select date '2016-01-01' from dual
union all select add_months(dt,1) from dates where dt < date '2020-01-01'
)
select d.dt,count(distinct t.client_number) count_of_client_numbers
from dates d
left join title t
on t.issue_date <= d.dt
and t.expiry_date > d.dt
group by d.dt
这种方法的好处是,您可以获得每年的结果,甚至没有标题开始或结束的地方。