我尝试了三种方法,所有方法都可以,但是得到不同的结果:
SELECT @age = DATEDIFF(YY, x.BirthDate, x.LastVisitDate)
SELECT @age = (CONVERT(int,CONVERT(char(8),x.LastVisitDate,112)) - CONVERT(char(8),x.BirthDate,112)) / 10000
SELECT @age = FLOOR(DATEDIFF(DAY, x.BirthDate , x.LastVisitDate) / 365.25)
第一个我得到63,第二个和第三个我得到62,哪个是正确的?
答案 0 :(得分:1)
只需使用大型机时代的古老算法:
SELECT @age = (
(YEAR(x.LastVisitDate) * 10000 + MONTH(x.LastVisitDate) * 100 + DAY(x.LastVisitDate))
-
(YEAR(x.BirthDate)* 10000 + MONTH(x.BirthDate) * 100 + DAY(x.BirthDate))
) / 10000
答案 1 :(得分:0)
一个人一年中的生日年龄是(岁-出生年份) 这就是带有yy参数的datediff的结果。如果他们还没有生日,那么您必须减去一年,这就是我的IIF所做的。
您已经发现,其他方法也存在缺陷。例如,我体验到/365.25天有时会在一个人的生日前后出错,并且如果他们出生于2月29日,这是一个额外的技巧
SELECT @age = DATEDIFF(YY, x.BirthDate, x.LastVisitDate) -
IIF(MONTH(x.LastVisitDate) < MONTH(x.BirthDate)
OR MONTH(x.LastVisitDate) = MONTH(x.BirthDate) AND DAY(x.LastVisitDate) < DAY(x.BirthDate)
, 1
, 0
)
答案 2 :(得分:0)
尝试使用此标量函数。 它带有三个参数。
开始日期和结束日期以及增加一天的额外选项。
该函数以“ YY MM DD”的形式返回结果。有几个例子
SELECT dbo.CalcDate(NULL, GETDATE(), 0); --> NULL
SELECT dbo.CalcDate(GETDATE(), GETDATE(), 0); --> 0 0 0
SELECT dbo.CalcDate(GETDATE(), GETDATE(), 1); ---> 0 0 1
SELECT dbo.CalcDate('20150101', '20161003', 0); ---> 1 9 2
SELECT dbo.CalcDate('20031101', '20161003', 0); --->12 11 2
SELECT dbo.CalcDate('20040731', '20040601', 0); ---> 0 1 30
SELECT dbo.CalcDate('20040731', '20040601', 1); ---> 0 2 0
并且源代码在下面的代码段中列出。
CREATE FUNCTION [dbo].[CalcDate]
(
@dwstart datetime, @dwend datetime,@extraDay bit
)
RETURNS nvarchar(20)
BEGIN
DECLARE @yy int;
DECLARE @mm int;
DECLARE @dd int;
DECLARE @increment int;
SET @increment = 0;
DECLARE @monthDay TABLE
(
monthno int, monthdayno int
);
DECLARE @dStart AS datetime;
DECLARE @dEnd AS datetime;
INSERT INTO @monthDay
VALUES (1, 31);
INSERT INTO @monthDay
VALUES (2, -1);
INSERT INTO @monthDay
VALUES (3, 31);
INSERT INTO @monthDay
VALUES (4, 30);
INSERT INTO @monthDay
VALUES (5, 31);
INSERT INTO @monthDay
VALUES (6, 30);
INSERT INTO @monthDay
VALUES (7, 31);
INSERT INTO @monthDay
VALUES (8, 31);
INSERT INTO @monthDay
VALUES (9, 30);
INSERT INTO @monthDay
VALUES (10, 31);
INSERT INTO @monthDay
VALUES (11, 30);
INSERT INTO @monthDay
VALUES (12, 31);
--The order of the arguments is not important
IF @dwStart > @dWEnd
BEGIN
SET @dStart = @dWEnd;
SET @dEnd = @dWStart;
END;
ELSE
BEGIN
SET @dStart = @dWStart;
SET @dEnd = @dWEnd;
END;
--
DECLARE @d1 AS INT;
SET @d1 = DAY(@dStart);
DECLARE @d2 AS int;
SET @d2 = DAY(@dEnd);
IF @d1 > @d2
BEGIN
SET @increment = (SELECT
monthdayno
FROM @monthDay
WHERE monthno = MONTH(@dStart));
END;
IF @increment = -1
BEGIN
--Is it a leap year
SET @increment = (SELECT
CASE
WHEN ISDATE(CAST(YEAR(@dStart) AS CHAR(4)) + '0229') = 1 THEN 29
ELSE 28
END);
END;
IF @increment != 0
BEGIN
SET @DD = DAY(@dEnd) + @increment - DAY(@dStart) + (CASE
WHEN @extraDay = 1 THEN 1
ELSE 0
END);
SET @increment = 1;
END;
ELSE
BEGIN
SET @dd = DAY(@dEnd) - DAY(@dStart) + (CASE
WHEN @extraDay = 1 THEN 1
ELSE 0
END);
END;
IF (MONTH(@dStart) + @increment) > MONTH(@dEnd)
BEGIN
SET @mm = MONTH(@dEnd) + 12 - (MONTH(@dStart) + @increment);
SET @increment = 1;
END;
ELSE
BEGIN
SET @mm = MONTH(@dEnd) - (MONTH(@dStart) + @increment);
SET @increment = 0;
END;
SET @yy = YEAR(@dEnd) - (YEAR(@dStart) + @increment);
IF @dd >= 31
BEGIN
SET @mm = @mm + 1;
SET @dd = @dd - 31;
END;
IF @mm >= 12
BEGIN
SET @yy = @yy + 1;
SET @mm = @mm - 12;
END;
RETURN (CONVERT(NVARCHAR(2), @yy) + ' ' + CONVERT(NVARCHAR(2), @mm) + ' ' + CONVERT(NVARCHAR(2), @dd));
END;
答案 3 :(得分:0)
如果您要某人的年龄,则取“年”之差,然后根据MMDD的顺序减去一个。所以:
select (year(x.LastVisitDate) - year(x.BirthDate) -
(case when month(x.LastVisitDate) < month(x.BirthDate)
then 1
when month(x.LastVisitDate) = month(x.BirthDate) and
day(x.LastVisitDate) < day(x.BirthDate)
then 1
else 0
end)
) as age
这对于for年和leap日应该是正确的,并且仅在某人的生日(或者如果生日是2月29日,然后在3月1日)上增加年龄。
您还可以使用MMDD表示并执行以下操作来表达case
表达式:
(case when ( month(x.LastVisitDate) * 100 + day(x.LastVisitDate) <
month(x.BirthDate) * 100 + day(x.BirthDate
)
then 1
then 1
else 0
end)
使用DATEDIFF()
的方法根本不起作用(很容易),因为DATEDIFF()
不在计算两个时间段之间的差,而是在它们之间的时间间隔数。
使用天数差除以365.25是一个近似值,并且在生日前后会自动消失。
使用日历规则(例如上述规则)应该会产生正确的结果。