如何获得不同年份的年龄计算

时间:2016-11-09 07:07:17

标签: sql sql-server tsql date datetime

我有一些这样的示例数据:

DECLARE @T Table (ID INT, Name VARCHAR(10), DOB DATE)
INSERT INTO @T (ID, Name, DOB) VALUES (1,'Mohan', '1937-12-01')
INSERT INTO @T (ID, Name, DOB) VALUES (2,'Raj',   '1936-12-25')
INSERT INTO @T (ID, Name, DOB) VALUES (5,'Manny', '1937-01-30')
INSERT INTO @T (ID, Name, DOB) VALUES (3,'kamal', '1938-12-12')
INSERT INTO @T (ID, Name, DOB) VALUES (4,'Raj',   '1937-05-12')

SELECT * FROM  @T

通过使用以下查询,我将找到年,月,日的年龄

SELECT Name,cast((DATEDIFF(m, DOB, GETDATE())/12) as varchar) + ' Y & ' + 
   cast((DATEDIFF(m, DOB, GETDATE())%12) as varchar) + ' M & ' +
   cast((DATEDIFF(D, DOB, GETDATE())%12) as varchar) + ' d'  from @T 

我只是想知道未来45天内谁将达到78,79和80岁。

通过使用以下查询,我可以获得在未来45天内达到80年的数据

       where
DOB > DATEADD(year,-80,GETDATE()) and
DOB < DATEADD(year,-80,DATEADD(day,45,GETDATE()))
如果我通过80,它将一次提供一个数据,这将给出数据达到80年。如果我给出79,它将给出达到79年的数据。 但是我怎样才能在45天内达到78,79和80年的所有数据。

建议我最好的方式

 Name       Age
    Mohan   78 Y & 11 M & 9 d
    Raj     79 Y & 11 M & 2 d
    kamal   77 Y & 11 M & 5 d

以上人员在45天内达到各自的年份

Mohan 79 --> with in 45 days
Raj   80 --> with in 45 days
kamal 78 --> with in 45 days

7 个答案:

答案 0 :(得分:2)

要查找生日在接下来的45天内的所有人,通常最简单的方法是重置您在一年内比较的所有值,然后从那里开始工作:

DECLARE @T Table (ID INT,Name VARCHAR(10),DOB DATE)
INSERT INTO @T (ID,Name,DOB) VALUES (1,'Mohan','1937-12-01')
INSERT INTO @T (ID,Name,DOB) VALUES (2,'Raj','1936-12-25')
INSERT INTO @T (ID,Name,DOB) VALUES (5,'Manny','1937-01-30')
INSERT INTO @T (ID,Name,DOB) VALUES (3,'kamal','1938-12-12')
INSERT INTO @T (ID,Name,DOB) VALUES (4,'Raj','1937-05-12')

declare @Today date
--Set "Today" to today's date in 2000
set @Today = DATEADD(year,DATEDIFF(year,GETDATE(),'20000101'),GETDATE())
declare @Plus45 date
set @Plus45 = DATEADD(day,45,@Today)
--And reset to 2000 (year wrap-around)
set @Plus45 = DATEADD(year,DATEDIFF(year,@Plus45,'20000101'),@Plus45)
select @Today as Today,@Plus45 as Plus45

;With ResetDOBs as (
    select
        *,
        DATEADD(year,DATEDIFF(year,DOB,'20000101'),DOB) as DOB2000
    from
        @T
)
select
    *
from
    ResetDOBs
where
    DOB2000 between @Today and @Plus45 or
    (@Plus45 < @Today and
        (DOB2000 <= @Plus45 or DOB2000 >= @Today)
    )

结果:

ID          Name       DOB        DOB2000
----------- ---------- ---------- ----------
1           Mohan      1937-12-01 2000-12-01
3           kamal      1938-12-12 2000-12-12

如果它是闰年,我们可以使用任何一年进行重置。我选择2000.在计算@Plus45和最后的Where条款中,当45天的时间与年终转换重叠时,使用这种方法处理奇怪的事情还有一点点麻烦。 ,十二月/一月。

(在我的时区,它目前是2016-11-09,所以Raj(ID 2)还没有完全在45天的窗口内)

此查询:

SELECT Name,cast((DATEDIFF(m, DOB, GETDATE())/12) as varchar) + ' Y & ' + 
cast((DATEDIFF(m, DOB, GETDATE())%12) as varchar) + ' M & ' +
cast((DATEDIFF(D, DOB, GETDATE())%12) as varchar) + ' d'  from @T

仍然严重受伤。 Raj(身份证2)不会将他们的年龄报告为79岁和以上。 11 M&amp; 2 d,正如您所报告的那样。他们将年龄报告为79岁,10个月和几天。您的月计算很容易超过1,并且您的日计算会混淆(为什么%12计算一天?)。

这是进行Y / M / D计算的一种方法,应该更接近人们对人们年龄的期望。如果你有一个数字表,你可以用它来创建NumPairs CTE,而不是我在这里创建它的方式:

DECLARE @T Table (ID INT,Name VARCHAR(10),DOB DATE)
INSERT INTO @T (ID,Name,DOB) VALUES (1,'Mohan','1937-12-01')
INSERT INTO @T (ID,Name,DOB) VALUES (2,'Raj','1936-12-25')
INSERT INTO @T (ID,Name,DOB) VALUES (5,'Manny','1937-01-30')
INSERT INTO @T (ID,Name,DOB) VALUES (3,'kamal','1938-12-12')
INSERT INTO @T (ID,Name,DOB) VALUES (4,'Raj','1937-05-12')

declare @Today date
set @today = GETDATE()

;With NumPairs as (
    select 0 as n1, 1 as n2
    union all
    select n1+1,n2+1
    from NumPairs
    where n1 <= 150
)
select
    t.*,
    y.n1 as Y,
    m.n1 as M,
    d.n1 as D
from
    @T t
        cross apply
    (select n1,DATEADD(year,n1,DOB) as DOBy from NumPairs
    where DATEADD(year,n1,DOB) <= @today and
        DATEADD(year,n2,DOB) > @today
    ) y
        cross apply
    (select n1,DATEADD(month,n1,DOBy) as DOBmy from NumPairs
    where DATEADD(month,n1,DOBy) <= @today and
        DATEADD(month,n2,DOBy) > @today
    ) m
        cross apply
    (select n1 from NumPairs
    where DATEADD(day,n1,DOBmy) = @today
    ) d
option (maxrecursion 0)

结果:

ID          Name       DOB        Y           M           D
----------- ---------- ---------- ----------- ----------- -----------
3           kamal      1938-12-12 77          10          28
1           Mohan      1937-12-01 78          11          8
2           Raj        1936-12-25 79          10          15
5           Manny      1937-01-30 79          9           10
4           Raj        1937-05-12 79          5           28

答案 1 :(得分:1)

您可以先计算下一个年龄和下一个生日的天数,然后按它们进行过滤。

WITH y AS
(
    SELECT *, 
    DATEDIFF(hour,DOB,GETDATE())/8766 + 1  NextAge,
    DATEDIFF(DAY, GETDATE(), DATEADD(YEAR, DATEDIFF(hour,DOB,GETDATE())/8766 + 1, DOB)) ToNextBirthday
    FROM @T
)
SELECT * FROM y
WHERE
    y.NextAge IN (78, 79, 80)
    AND y.ToNextBirthday <= 45

修改

上述答案会在评论中提到的一些边缘案例中出现问题。 下面我借用this answer中的代码来计算NextAge。其余的逻辑仍然是相同的。

DECLARE @today DATE;
SET @today = GETDATE();

WITH a AS
(
    SELECT *, 
    (CONVERT(int,CONVERT(char(8), @today, 112))-CONVERT(char(8), DOB, 112))/10000 + 1 NextAge
    FROM @T
), b AS
(
    SELECT *,
    DATEDIFF(DAY, @today, DATEADD(YEAR, a.NextAge, DOB)) ToNextBirthday
    FROM a
)

SELECT * FROM b
WHERE
    b.NextAge IN (78, 79, 80)
    AND b.ToNextBirthday <= 45

答案 2 :(得分:1)

  

我只想知道即将到来的78,79和80岁的人   45天。

有一种更简单的方法来查看问题。你有一个日期范围:

[today, today + 45 days]

您需要检查某人是否在这些范围内有出生日期:

[today - 78 years, today + 45 days - 78 years]
[today - 79 years, today + 45 days - 79 years]
[today - 80 years, today + 45 days - 80 years]

查询只是变成:

DECLARE @D0 AS DATE = CURRENT_TIMESTAMP                    -- 2016-11-09
DECLARE @D1 AS DATE = DATEADD(DAY, 45, CURRENT_TIMESTAMP)  -- 2016-12-24

SELECT *
FROM @T
WHERE DOB BETWEEN DATEADD(YEAR, -78, @D0) AND DATEADD(YEAR, -78, @D1)
OR    DOB BETWEEN DATEADD(YEAR, -79, @D0) AND DATEADD(YEAR, -79, @D1)
OR    DOB BETWEEN DATEADD(YEAR, -80, @D0) AND DATEADD(YEAR, -80, @D1)

答案 3 :(得分:0)

where
DOB > DATEADD(year,-80,GETDATE()) and
DOB < DATEADD(year,-80,DATEADD(day,45,GETDATE()))

如果这样做,你可以添加一些'或子句'来实现你想要的东西(如果我做对了):

where
(DOB > DATEADD(year,-80,GETDATE()) and
DOB < DATEADD(year,-80,DATEADD(day,45,GETDATE())))
or
(DOB > DATEADD(year,-79,GETDATE()) and
DOB < DATEADD(year,-79,DATEADD(day,45,GETDATE())))
...

答案 4 :(得分:0)

SELECT * from @T 
WHERE 
        (DATEDIFF(dd,GETDATE(),DATEADD(yy,78,dob))<45
            AND 
         DATEDIFF(dd,GETDATE(),DATEADD(yy,78,dob))>0)
OR
        (DATEDIFF(dd,GETDATE(),DATEADD(yy,79,dob))<45
            AND 
         DATEDIFF(dd,GETDATE(),DATEADD(yy,79,dob))>0)
OR
        (DATEDIFF(dd,GETDATE(),DATEADD(yy,80,dob))<45
            AND 
         DATEDIFF(dd,GETDATE(),DATEADD(yy,80,dob))>0)

答案 5 :(得分:0)

尝试

DECLARE @T Table (ID INT,Name VARCHAR(10),DOB DATE)
INSERT INTO @T (ID,Name,DOB) VALUES (1,'Mohan','1937-12-01')
INSERT INTO @T (ID,Name,DOB) VALUES (2,'Raj','1936-12-25')
INSERT INTO @T (ID,Name,DOB) VALUES (5,'Manny','1937-01-30')
INSERT INTO @T (ID,Name,DOB) VALUES (3,'kamal','1938-12-12')
INSERT INTO @T (ID,Name,DOB) VALUES (4,'Raj','1937-05-12')

declare @dd date = dateadd(day,45,getdate());
declare @dmd int = month(@dd)*100+day(@dd);
select @dd, @dmd;
select *
from  @T
where datediff(year, DOB, @dd) - case when month(DOB)*100+day(DOB) > @dmd then 1 else 0 end in (78,79,80)
order by DOB;

答案 6 :(得分:0)

我曾经使用SQL函数来计算年龄,我希望它也可以帮助你满足你的要求。

但是你的问题还有一个方面,你想提前45天看到

因此,我们需要在现在添加45天,然后calculate age in SQL

,而不是计算当前日期的年龄。

我是这样做的

DECLARE @T Table (ID INT, Name VARCHAR(10), DOB DATE)
INSERT INTO @T (ID, Name, DOB) VALUES (1,'Mohan', '1937-12-01')
INSERT INTO @T (ID, Name, DOB) VALUES (2,'Raj',   '1936-12-25')
INSERT INTO @T (ID, Name, DOB) VALUES (5,'Manny', '1937-01-30')
INSERT INTO @T (ID, Name, DOB) VALUES (3,'kamal', '1938-12-12')
INSERT INTO @T (ID, Name, DOB) VALUES (4,'Raj',   '1937-05-12')
INSERT INTO @T (ID, Name, DOB) VALUES (3,'kodyaz', '2015-12-25')
INSERT INTO @T (ID, Name, DOB) VALUES (3,'eralper', '2015-12-24')

SELECT 
*, 
dbo.fn_CalculateAge(DOB,dateadd(dd,45,getdate())) fo
FROM  @T
--where
--dbo.fn_CalculateAge(DOB,dateadd(dd,45,getdate())) = 79 and
--dbo.fn_CalculateAge(DOB,getdate()) = 78

请注意,如果您取消注释WHERE子句,您将获得现在为78岁且在45天内为79岁的人

我希望它有所帮助,