SQL 计算十年内存在的记录

SQL to Count Records that Existed by Decade

我有一个 Oracle a table,它有 3 列。 FILE_NUM、START_DATE、END_DATE。 FILE_NUM 是唯一标识符,因此每一行都是唯一的。

FILE_NUM START_DATE END_DATE
1111 Apr. 04, 1977 Jun. 30, 1984
1112 Jan. 03, 1987 Sep. 05, 2010
1113 May. 14, 1962 Jan. 30, 1998
1114 Oct. 09, 2001 Aug. 22, 2025
1113 May. 14, 1962 Jan. 30, 1998
1114 Nov. 18, 2003 Aug. 22, 2028
etc

我想查询每十年存在的文件数。类似于:

Decade Count
1960-1969 10
1970-1979 25
1980-1989 42

逻辑是,如果该文件在任何十年的任何时间点存在,则将其计入这十年中的每一个。所以对于 file_num 1112,应该算在 1980 年代、1990 年代、2000 年代和 2010 年代。

我什至不知道这是否可能。我已经在我的查询中修改了几次,但我不确定我是否知道足够的函数或技术来获得这种结果。

感谢您的帮助。

编辑:

我应该说明如何进行计数。我需要以 3 种方式处理日期范围,以便捕获每个十年内存在哪些 file_num。

  1. 如果它在十进制范围内开始,算上它。
  2. 如果它在十进制范围内结束,算它。
  3. 如果它在十进制范围之前开始并在十进制范围之后结束,则计算它。

我制作了以下 SQL。我仍在试图弄清楚它是否在做我想让它做的事情。如果有人有建议

with decades as
  (
  select
    concat(concat(floor(extract(year from t.start_date)/10)*10, '-'), floor(extract(year from t.start_date)/10)*10 + 9) DECADE
  from 
    table t
  group by
    concat(concat(floor(extract(year from t.start_date)/10)*10, '-'), floor(extract(year from t.start_date)/10)*10 + 9)
  )

select
  count(a.file_num),
  decades.decade
from
  table a,
  decades
where 
  extract(year from a.start_date) between extract(year from to_date(SUBSTR(decades.decade,0,4), 'YYYY')) and extract(year from to_date(SUBSTR(decades.decade,6,9), 'YYYY'))
  or
  extract(year from a.end_date) between extract(year from to_date(SUBSTR(decades.decade,0,4), 'YYYY')) and extract(year from to_date(SUBSTR(decades.decade,6,9), 'YYYY'))
  or
  (extract(year from a.start_date) < extract(year from to_date(SUBSTR(decades.decade,0,4), 'YYYY'))
   and
   extract(year from a.end_date) > extract(year from to_date(SUBSTR(decades.decade,6,9), 'YYYY'))
  )  
group by
  decades.decade
order by
  decades.decade

最好的选择可以是十年维度 table:

并加入主要 table:

select d.decade, 
       count(file_num) as count 
  from table m
  join decade d
    on m.start_date >= d.decade_start_date
  join decade d2
    on m.end_date <= d2.decade_end_date
 where 1 = 1
   and d.decade = d2.decade 
 group by 1

您应该能够通过将日期的年份除以 10 转换为一个整数,然后将其乘以 10 来组合一些东西。示例...

2019 / 10 = 201.9 cast as integer = 201 * 10 = 2010

然后,在上面加上 9 年作为结束年份

2019 + 10 = 2029 / 10 = 202.9 cast as integer = 202 * 10 = 2020 + 9 = 2029

所以,您应该关心的是开始日期...类似

select
      concat( cast( EXTRACT(YEAR FROM m.start_date ) / 10 as int ) * 10, 
             concat( '-', 
             cast( EXTRACT(YEAR FROM m.start_date ) / 10 as int ) * 10 + 9)),
      count(*) as NumRecs
   from
      table m
   group by 1

您也可以利用 connect by 子句来做到这一点。 我假设您的真实数据中没有任何重复行(这些列 FILE_NUM、START_DATE、END_DATE 应该是唯一的)。

SELECT dec_start, dec_end, COUNT(*) nb
FROM (
    SELECT t.*, level
      , 10 * trunc( extract ( year from (START_DATE) ) / 10 ) + 10 * LEVEL - 10 dec_start
      , 10 * trunc( extract ( year from (START_DATE) ) / 10 ) + 10 * LEVEL - 1 dec_end
    FROM YourTable T
    CONNECT BY 
        10 * TRUNC( EXTRACT ( YEAR FROM (START_DATE) ) / 10 ) + 10 * LEVEL - 10 
            <   10 * CEIL( EXTRACT ( YEAR FROM (END_DATE) ) / 10 )
    AND PRIOR FILE_NUM = FILE_NUM
    AND PRIOR START_DATE = START_DATE
    AND PRIOR END_DATE = END_DATE
    AND PRIOR SYS_GUID() IS NOT NULL
)
group by dec_start, dec_end 
order by dec_start, dec_end
;

demo on db<>fiddle