Sql server 从SSN计算年龄

Sql server 从SSN计算年龄,sql-server,reporting-services,Sql Server,Reporting Services,我在SSRS的一个项目中工作 在数据库中,我有一个名为X的列,在这个列中,我有所有员工的社会保险号码,所有号码都是这样的,没有任何-或/例如1111111111 DDMMYYXXXX 我的问题是,我如何编写一个sql,只选择6个第一个数字,然后减去当前时间,最后给出员工的年龄。谁能给我指一下正确的方向吗。 谢谢 到目前为止,我编写的sql如下所示: create function dbo.birthdate_from_cpr(@cpr varchar(10)) returns date as b

我在SSRS的一个项目中工作

在数据库中,我有一个名为X的列,在这个列中,我有所有员工的社会保险号码,所有号码都是这样的,没有任何-或/例如1111111111 DDMMYYXXXX

我的问题是,我如何编写一个sql,只选择6个第一个数字,然后减去当前时间,最后给出员工的年龄。谁能给我指一下正确的方向吗。 谢谢

到目前为止,我编写的sql如下所示:

create function dbo.birthdate_from_cpr(@cpr varchar(10))
returns date
as
begin
  declare @year char(2) = substring(@cpr, 5, 2),
          @month char(2) = substring(@cpr, 3, 2),
          @day char(2) = substring(@cpr, 1, 2),
          @century char(2)



  if right(datepart(yy, getdate()), 2) < @year
    set @century = left(datepart(yy, getdate()) - 100, 2)
  else
    set @century = left(datepart(yy, getdate()), 2)


  return convert(date, @century + @year + @month + @day, 120)
end
go

select dbo.birthdate_from_cpr('1312761234'),
       dbo.birthdate_from_cpr('0101041234'),
       age = datediff(yy, dbo.birthdate_from_cpr('1312761234'), getdate())
convert(date, substring(Users.SSN , 17, 2) + substring(Users.SSN , 15, 2) + substring(Users.SSN , 13, 2), 12)
一种方法是使用和创建一个格式良好的字符串,并将其更改为日期值,然后就可以了

不要担心查询的长度,它只是您需要的最后一列。我选择在不同的专栏中展示每一步

DECLARE @SSN char(10) = '1309761234'

SELECT  @SSN as OriginalString,
        STUFF(
             STUFF(LEFT(@SSN, 6), 3, 0, '.')
            , 6, 0, '.') As DateString,
       CONVERT(date, 
               STUFF(
                     STUFF(LEFT(@SSN, 6), 3, 0, '.')
               , 6, 0, '.')
       , 4) As Date, -- German, no century - dd.mm.yy
        DATEDIFF(YEAR, 
                    CONVERT(date, 
                            STUFF(LEFT(@SSN, 4), 3, 0, '.') +'.'+
                            CAST(DATEPART(YEAR, GETDATE()) / 100 - 1 as char(2)) + 
                            SUBSTRING(@SSN, 5, 2)
                    , 104) 
                 , GETDATE()) As Age
结果:

OriginalString  DateString  Date                    Age
1309761234      13.09.76    13.09.1976 00:00:00     41
还有你的问题:

SELECT Users.Id, Users.FirstName + ' ' + Users.LastName AS Medarbajder,
Users.SSN AS CPRNR, 
CASE WHEN Users.SSN IS NOT NULL THEN
DATEDIFF(YEAR, 
        CONVERT(date, 
                            STUFF(LEFT(Users.SSN, 4), 3, 0, '.') +'.'+
                            CAST(DATEPART(YEAR, GETDATE()) / 100 - 1 as char(2)) + 
                            SUBSTRING(Users.SSN, 5, 2)
                    , 104) 
, GETDATE()) 
ELSE
NULL
END As Age,
convert(varchar(10), Paychecks.WorkStartDate, 105) AS StartDato ,
Paychecks.DepartmentName AS Afdelinger

FROM dbo.Paychecks, dbo.Users
WHERE Users.CustomerId=214 AND Users.Id=Paychecks.UserId order by Users.FirstName;

您需要从ssn列中提取日期以计算年龄,假设您的格式为1111111 DDMMYYXXXX。但是格式字符串DDMMYY本身不容易转换,因此我们需要将其转换为函数可以识别的格式

大概是这样的:

create function dbo.birthdate_from_cpr(@cpr varchar(10))
returns date
as
begin
  declare @year char(2) = substring(@cpr, 5, 2),
          @month char(2) = substring(@cpr, 3, 2),
          @day char(2) = substring(@cpr, 1, 2),
          @century char(2)



  if right(datepart(yy, getdate()), 2) < @year
    set @century = left(datepart(yy, getdate()) - 100, 2)
  else
    set @century = left(datepart(yy, getdate()), 2)


  return convert(date, @century + @year + @month + @day, 120)
end
go

select dbo.birthdate_from_cpr('1312761234'),
       dbo.birthdate_from_cpr('0101041234'),
       age = datediff(yy, dbo.birthdate_from_cpr('1312761234'), getdate())
convert(date, substring(Users.SSN , 17, 2) + substring(Users.SSN , 15, 2) + substring(Users.SSN , 13, 2), 12)
从那时起,这是一件简单的事情


请注意,SQL Server将把00到49年视为本世纪。对于老年人来说,这可能是一个问题……

我建议创建一个UDF,将CPR转换为一个日期,这将使您的生活在未来更容易进行分析,并且您可以更轻松地进行测试。这个版本解决了@paul bambury提到的世纪问题,假设没有人超过100岁

create function dbo.birthdate_from_cpr(@cpr varchar(10))
returns date
as
begin
  declare @year char(2) = substring(@cpr, 5, 2),
          @month char(2) = substring(@cpr, 3, 2),
          @day char(2) = substring(@cpr, 1, 2),
          @century char(2)

  -- if the current 2 digit year is less than the birthday year, assume it was last century
  -- e.g. 76 should be 1976 but 02 should be 2002
  if right(datepart(yy, getdate()), 2) < @year
    set @century = left(datepart(yy, getdate()) - 100, 2)
  else
    set @century = left(datepart(yy, getdate()), 2)


  return convert(date, @century + @year + @month + @day, 120)
end
go

select dbo.birthdate_from_cpr('1312761234'),
       dbo.birthdate_from_cpr('0101041234'),
       age = datediff(yy, dbo.birthdate_from_cpr('1312761234'), getdate())

DATEDIFFYEAR,CASTLEFTcolName,6 AS DATE,GETDATELEFTUsers.SSN,6这是什么样子的?您可以共享示例表数据和预期的输出。DATEDIFFYEAR,CONVERTDATE,CONVERTVARCHAR10,LEFTUsers.SSN,6,GETDATE试试这个。这可能是一个括号问题,但这是否是一个安全的假设,即没有员工超过100人?感谢所有这些,但我得到了错误:关键字“convert”附近的语法不正确。我得到了另一个错误:从字符串转换日期和时间时转换失败。您确定它是ddmmyy吗?我没有您的示例数据可供使用,这就是我自己创建示例数据的原因。列的实际长度是不相关的,只要它至少有6个字符长,因为我们只对前6个字符感兴趣。0101012342转换为2001年1月1日。表中至少有一个数字不能转换为ddmmyy。如果您使用的是2012版本或更高版本,请将转换替换为try_convert,并查看从何处获得空值。这些是无法转换的数字。也许空值就是问题所在。我已经编辑了我的答案以忽略空值。请您也写一个查询,我不太理解UDF: