SQL Сервер Получить все дни рождения - PullRequest
0 голосов
/ 02 марта 2020

У меня есть таблица в SQL Сервер, который состоит из


ID, B_Day


1, 1977-02-20


2, 2001-03-10


...

Я хочу добавить строки в эту таблицу для каждого года дня рождения, вплоть до текущего года рождения. т.е.:

ID, B_Day


1,1977-02-20


1,1978-02-20


1,1979-02-20


...


1,2020-02-20


2, 2001-03-10


2, 2002-03-10


...


2 , 2019-03-10


Я изо всех сил пытаюсь определить, какова лучшая стратегия для достижения этой цели. Я думал о рекурсивном самосоединении, но это создает слишком много слоев. Есть предложения?

Ответы [ 3 ]

1 голос
/ 02 марта 2020

Следующее должно работать

with row_gen
  as (select top 200 row_number() over(order by name)-1 as rnk
        from master..spt_values
     )
select a.id,a.b_day,dateadd(year,rnk,b_day) incr_b_day
  from dbo.t a
  join row_gen b
    on dateadd(year,b.rnk,a.b_day)<=getdate()

https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=0d06c95e1914ca45ca192d0d192bd2e0

0 голосов
/ 02 марта 2020

Если ваш набор данных не слишком велик, можно использовать рекурсивный запрос:

with cte as (
    select id, b_day bday0, b_day, 1 lvl from mytable
    union all
    select 
        id, 
        bday0, 
        dateadd(year, lvl, bday0), lvl + 1 
    from cte 
    where dateadd(year, lvl, bday0) <= getdate()
)
select id, b_day from cte order by id, b_day

Демонстрация на DB Fiddle :

id | b_day     
-: | :---------
 1 | 1977-02-20
 1 | 1978-02-20
 1 | 1979-02-20
 1 | 1980-02-20
 1 | 1981-02-20
 1 | 1982-02-20
 1 | 1983-02-20
 1 | 1984-02-20
 1 | 1985-02-20
 1 | 1986-02-20
 1 | 1987-02-20
 1 | 1988-02-20
 1 | 1989-02-20
 1 | 1990-02-20
 1 | 1991-02-20
 1 | 1992-02-20
 1 | 1993-02-20
 1 | 1994-02-20
 1 | 1995-02-20
 1 | 1996-02-20
 1 | 1997-02-20
 1 | 1998-02-20
 1 | 1999-02-20
 1 | 2000-02-20
 1 | 2001-02-20
 1 | 2002-02-20
 1 | 2003-02-20
 1 | 2004-02-20
 1 | 2005-02-20
 1 | 2006-02-20
 1 | 2007-02-20
 1 | 2008-02-20
 1 | 2009-02-20
 1 | 2010-02-20
 1 | 2011-02-20
 1 | 2012-02-20
 1 | 2013-02-20
 1 | 2014-02-20
 1 | 2015-02-20
 1 | 2016-02-20
 1 | 2017-02-20
 1 | 2018-02-20
 1 | 2019-02-20
 1 | 2020-02-20
 2 | 2001-03-01
 2 | 2002-03-01
 2 | 2003-03-01
 2 | 2004-03-01
 2 | 2005-03-01
 2 | 2006-03-01
 2 | 2007-03-01
 2 | 2008-03-01
 2 | 2009-03-01
 2 | 2010-03-01
 2 | 2011-03-01
 2 | 2012-03-01
 2 | 2013-03-01
 2 | 2014-03-01
 2 | 2015-03-01
 2 | 2016-03-01
 2 | 2017-03-01
 2 | 2018-03-01
 2 | 2019-03-01
 2 | 2020-03-01
0 голосов
/ 02 марта 2020

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

with cte as (
     select t.id, t.b_day, convert(date, getdate()) as mx_dt
     from table t
     union all
     select c.id, dateadd(year, 1, c.b_day), c.mx_dt
     from cte c
     where dateadd(year, 1, c.b_day) < c.mx_dt
)
select c.id, c.b_day
from cte c
order by c.id, c.b_day;

По умолчанию рекурсия 100, вы можете добавить подсказку запроса для дополнительной рекурсии option (maxrecursion 0).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...