Рассчитайте возраст лицензии на каждый год с момента выдачи. Oracle SQL - PullRequest
1 голос
/ 28 мая 2020

У меня есть таблица с записями лицензий. В таблице содержится уникальный номер лицензии и дата ее выдачи.

License #      Issue Date      
1234           2018-FEB-01
5678           2016-MAR-15
9012           1991-JAN-22
3456           2005-SEP-25

Мне нужно создать отчет, который вычисляет возраст лицензии каждый год с момента ее выдачи (округляется до ближайшего года) на указанную c дату. В этом случае sysdate в порядке.

Итак, я ищу что-то вроде этого:

License#     Year    License_Age
1234         2018    0
1234         2019    1
1234         2020    2
5678         2016    0 
5678         2017    1
5678         2018    2
5678         2019    3
5678         2020    4

Это будет использоваться в большем количестве запросов, которые рассчитывают сборы за каждый год на основе тарифный план. Плата увеличивается каждые 5 лет или около того, однако, если я смогу разобраться в тонкостях этой части запроса, я буду хорошо разбираться в остальном.

Вот мой базовый c синтаксис. Я могу узнать текущий возраст лицензии прямо сейчас, но я действительно не уверен, как вычислить возраст для каждого года с момента ее выдачи:

select floor(months_between(sysdate, a.issue_date) /12) as Years 
from
myTable a
where
a.license_number = 1234 --using this specific license number to see if my result returns what I want

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Вы можете использовать рекурсивный запрос и добавить 12 месяцев, а затем использовать EXTRACT, чтобы получить год в конце (не используйте только год в рекурсивном запросе, иначе вы получите строки для текущего года, где дата начала будет после текущей даты):

WITH license_years ( license_no, issue_date, license_age ) AS (
  SELECT license_no, issue_date, 0
  FROM   table_name
UNION ALL
  SELECT license_no, ADD_MONTHS( issue_date, 12 ), license_age + 1
  FROM   license_years
  WHERE  issue_date <= ADD_MONTHS( SYSDATE, -12 )
)
SELECT license_no,
       issue_date AS start_of_license_year,
       EXTRACT( YEAR FROM issue_date ) AS year,
       license_age
FROM   license_years
ORDER BY license_no,
       license_age

Что для ваших тестовых данных:

CREATE TABLE table_name ( License_no, Issue_Date ) AS
SELECT 1234, DATE '2018-02-01' FROM DUAL UNION ALL
SELECT 5678, DATE '2016-03-15' FROM DUAL UNION ALL
SELECT 9012, DATE '1991-01-22' FROM DUAL UNION ALL
SELECT 3456, DATE '2005-09-25' FROM DUAL;

Вывод:

LICENSE_NO | START_OF_LICENSE_YEAR | YEAR | LICENSE_AGE
---------: | :-------------------- | ---: | ----------:
      1234 | 2018-02-01            | 2018 |           0
      1234 | 2019-02-01            | 2019 |           1
      1234 | 2020-02-01            | 2020 |           2
      3456 | 2005-09-25            | 2005 |           0
      3456 | 2006-09-25            | 2006 |           1
      3456 | 2007-09-25            | 2007 |           2
      3456 | 2008-09-25            | 2008 |           3
      3456 | 2009-09-25            | 2009 |           4
      3456 | 2010-09-25            | 2010 |           5
      3456 | 2011-09-25            | 2011 |           6
      3456 | 2012-09-25            | 2012 |           7
      3456 | 2013-09-25            | 2013 |           8
      3456 | 2014-09-25            | 2014 |           9
      3456 | 2015-09-25            | 2015 |          10
      3456 | 2016-09-25            | 2016 |          11
      3456 | 2017-09-25            | 2017 |          12
      3456 | 2018-09-25            | 2018 |          13
      3456 | 2019-09-25            | 2019 |          14
      5678 | 2016-03-15            | 2016 |           0
      5678 | 2017-03-15            | 2017 |           1
      5678 | 2018-03-15            | 2018 |           2
      5678 | 2019-03-15            | 2019 |           3
      5678 | 2020-03-15            | 2020 |           4
      9012 | 1991-01-22            | 1991 |           0
      9012 | 1992-01-22            | 1992 |           1
      9012 | 1993-01-22            | 1993 |           2
      9012 | 1994-01-22            | 1994 |           3
      9012 | 1995-01-22            | 1995 |           4
      9012 | 1996-01-22            | 1996 |           5
      9012 | 1997-01-22            | 1997 |           6
      9012 | 1998-01-22            | 1998 |           7
      9012 | 1999-01-22            | 1999 |           8
      9012 | 2000-01-22            | 2000 |           9
      9012 | 2001-01-22            | 2001 |          10
      9012 | 2002-01-22            | 2002 |          11
      9012 | 2003-01-22            | 2003 |          12
      9012 | 2004-01-22            | 2004 |          13
      9012 | 2005-01-22            | 2005 |          14
      9012 | 2006-01-22            | 2006 |          15
      9012 | 2007-01-22            | 2007 |          16
      9012 | 2008-01-22            | 2008 |          17
      9012 | 2009-01-22            | 2009 |          18
      9012 | 2010-01-22            | 2010 |          19
      9012 | 2011-01-22            | 2011 |          20
      9012 | 2012-01-22            | 2012 |          21
      9012 | 2013-01-22            | 2013 |          22
      9012 | 2014-01-22            | 2014 |          23
      9012 | 2015-01-22            | 2015 |          24
      9012 | 2016-01-22            | 2016 |          25
      9012 | 2017-01-22            | 2017 |          26
      9012 | 2018-01-22            | 2018 |          27
      9012 | 2019-01-22            | 2019 |          28
      9012 | 2020-01-22            | 2020 |          29

(Примечание: для лицензии № 3456 нет строки 2020, так как это еще не сентябрь.)

db <> fiddle здесь

1 голос
/ 28 мая 2020

Вы можете использовать для этого рекурсивный запрос:

with cte (license#, year, age) as (
    select license#, extract(year from issue_date), 0 from mytable
    union all
    select license#, year + 1, age + 1 from cte where year < extract(year from sysdate)
)
select * from cte order by license#, year

Для первых двух строк ваших демонстрационных данных этот запрос возвращает :

LICENSE# | YEAR | AGE
-------: | ---: | --:
    1234 | 2018 |   0
    1234 | 2019 |   1
    1234 | 2020 |   2
    5667 | 2016 |   0
    5667 | 2017 |   1
    5667 | 2018 |   2
    5667 | 2019 |   3
    5667 | 2020 |   4
...