2009-11-10 67 views
3

(使用SQL Server 2008)按年齡計算的SQL數據壽命暴露時間

我需要一些幫助來形象化解決方案。比方說,我有以下簡單的表,退休金計劃的成員:

[Date of Birth]  [Date Joined]  [Date Left] 
1970/06/1   2003/01/01   2007/03/01 

我需要計算的生活各年齡組的人數從2000年到2009年

注:「年齡」的定義作爲1月1日這些每位年輕人的「最後一個生日的年齡」(或「ALB」)。例如如果你正好是41.35或41.77等年歲在2009年1月1日,那麼你將是ALB 41.

因此,如果上面的記錄是數據庫中的唯一條目,那麼輸出將如下所示:

[Year] [Age ]  [Number of Lives] 
2003  32   1 
2004  33   1 
2005  34   1 
2006  35   1 
2007  36   1 

(2000年,2001年,2002年,2008年和2009年有在文件中沒有生命因爲唯一的成員才加入對2003年1月1日和留在1/3/2007)

希望我讓自己清楚。

任何人有任何建議嗎?

謝謝,卡爾

[編輯]

添加另一層問題:

,如果我有什麼:

[Date of Birth] [Date Joined] [Date Left] [Gender] [Pension Value] 
1970/06/1   2003/01/01  2007/03/01 'M'  100,000 

,我想輸出是:

[Year] [Age ] [Gender] sum([Pension Value]) [Number of Lives] 
2003  32  M  100,000    1 
2004  33  M  100,000    1 
2005  34  M  100,000    1 
2006  35  M  100,000    1 
2007  36  M  100,000    1 

有什麼想法?

回答

1

你可以嘗試這樣的事情

DECLARE @Table TABLE(
     [Date of Birth] DATETIME, 
     [Date Joined] DATETIME, 
     [Date Left] DATETIME 
) 

INSERT INTO @Table ([Date of Birth],[Date Joined],[Date Left]) SELECT '01 Jun 1970', '01 Jan 2003', '01 Mar 2007' 
INSERT INTO @Table ([Date of Birth],[Date Joined],[Date Left]) SELECT '01 Jun 1979', '01 Jan 2002', '01 Mar 2008' 

DECLARE @StartYear INT, 
     @EndYear INT 

SELECT @StartYear = 2000, 
     @EndYear = 2009 

;WITH sel AS(
    SELECT @StartYear YearVal 
    UNION ALL 
    SELECT YearVal + 1 
    FROM sel 
    WHERE YearVal < @EndYear 
) 
SELECT YearVal AS [Year], 
     COUNT(Age) [Number of Lives] 
FROM (
      SELECT YearVal, 
        YearVal - DATEPART(yy, [Date of Birth]) - 1 Age 
      FROM sel LEFT JOIN 
        @Table ON DATEPART(yy, [Date Joined]) <= sel.YearVal 
          AND DATEPART(yy, [Date Left]) >= sel.YearVal 
     ) Sub 
GROUP BY YearVal 
+0

偉大的答案感謝。我喜歡@StartYear,@EndYear方法 – Karl 2009-11-10 16:15:19

+0

感謝您的答案 - 請參閱我的編輯了一個額外的複雜層,我不知道如何調整您的代碼來實現這一點。謝謝,卡爾 – Karl 2009-11-10 16:26:50

+0

我會在早上到這個X-) – 2009-11-10 17:31:44

0

處理這件(一些雜感) - 創建視圖來測試,如果你可以在你dev的步驟:

  1. ALB - 做一個查詢,對於一個給定的一年,向你memeber的ALB
  2. 年中的成員 - 另一位查詢,告訴您某位成員是否爲特定年份的成員
  3. 將這兩者放在一起,您應該能夠創建一個查詢,說明某人是否是給定成員一年以及他們的ALB是那年的。
  4. 嗯,棘手 - 遵循這一思路,你想要做的是生成一個表,該人員是該年的成員和他們的ALB(和一個唯一的ID)
  5. 從4. select year,alb,count(id)group by year,alb

我不確定我會從大約3的正確方向進行,但它應該可以工作。

您可能會發現一個有用的年份(臨時)表 - 將事情加入日期表中可以使各種事情成爲可能。

不是一個真正的答案,但肯定是一些方向......

2
WITH years AS 
     (
     SELECT 1900 AS y 
     UNION ALL 
     SELECT y + 1 
     FROM years 
     WHERE y < YEAR(GETDATE()) 
     ), 
     agg AS 
     (
     SELECT YEAR(Dob) AS Yob, YEAR(DJoined) AS YJoined, YEAR(DLeft) AS YLeft 
     FROM mytable 
     ) 
SELECT y, y - Yob, COUNT(*) 
FROM agg 
JOIN years 
ON  y BETWEEN YJoined AND YLeft 
GROUP BY 
     y, y - Yob 
OPTION (MAXRECURSION 0) 

出生在同一年總是有相同的年齡在你的模型,人們

這就是爲什麼如果他們去可言,他們總是進入一個小組,你只需要在他們停留在節目中的時間段內每年生成一行。

1

嘗試下面的示例查詢

SET NOCOUNT ON 

Declare @PersonTable as Table 
(
PersonId Integer, 
DateofBirth DateTime, 
DateJoined DateTime, 
DateLeft DateTime 
) 

INSERT INTO @PersonTable Values 
(1, '1970/06/10', '2003/01/01', '2007/03/01'), 
(1, '1970/07/11', '2003/01/01', '2007/03/01'), 
(1, '1970/03/12', '2003/01/01', '2007/03/01'), 
(1, '1973/07/13', '2003/01/01', '2007/03/01'), 
(1, '1972/06/14', '2003/01/01', '2007/03/01') 

Declare @YearTable as Table 
(
YearId Integer, 
StartOfYear DateTime 
) 

insert into @YearTable Values 
(1, '1/1/2000'), 
(1, '1/1/2001'), 
(1, '1/1/2002'), 
(1, '1/1/2003'), 
(1, '1/1/2004'), 
(1, '1/1/2005'), 
(1, '1/1/2006'), 
(1, '1/1/2007'), 
(1, '1/1/2008'), 
(1, '1/1/2009') 


;WITH AgeTable AS 
(
select StartOfYear, DATEDIFF (YYYY, DateOfBirth, StartOfYear) Age 
from @PersonTable 
Cross join @YearTable 
) 
SELECT StartOfYear, Age, COUNT (1) NumIndividuals 
FROM AgeTable 
GROUP BY StartOfYear, Age 
ORDER BY StartOfYear, Age 
+0

工作得很好,只是它沒有考慮到加入和離開的日期 – Karl 2009-11-10 16:14:10

1

首先一些準備有東西來測試:

CREATE TABLE People (
ID int PRIMARY KEY 
,[Name] varchar(50) 
,DateOfBirth datetime 
,DateJoined datetime 
,DateLeft datetime 
) 
go 

-- some data to test with 
INSERT INTO dbo.People 
VALUES 
    (1, 'Bob', '1961-04-02', '1999-01-01', '2007-05-07') 
    ,(2, 'Sadra', '1960-07-11', '1999-01-01', '2008-05-07') 
    ,(3, 'Joe', '1961-09-25', '1999-01-01', '2009-02-11') 
go 

-- helper table to hold years 
CREATE TABLE dimYear (
    CalendarYear int PRIMARY KEY 
) 
go 

-- fill-in years for report 
DECLARE 
    @yr int 
    ,@StartYear int 
    ,@EndYear int 

SET @StartYear = 2000 
SET @EndYear = 2009 

SET @yr = @StartYear 
WHILE @yr <= @EndYear 
    BEGIN 
     INSERT INTO dimYear (CalendarYear) values(@yr) 
     SET @yr [email protected]+1 
    END 

-- show test data and year tables 
select * from dbo.People 
select * from dbo.dimYear 
go 


然後函數返回人的年齡每一年,如果人仍一個活躍的成員。

-- returns [CalendarYear], [Age] for a member, if still active member in that year 
CREATE FUNCTION dbo.MemberAge(@DateOfBirth datetime, @DateLeft datetime) 
RETURNS TABLE 
AS 
RETURN (
    SELECT 
     CalendarYear, 
     CASE 
      WHEN DATEDIFF(dd, cast(CalendarYear AS varchar(4)) + '-01-01',@DateLeft) > 0 
       THEN DATEDIFF(yy, @DateOfBirth, cast(CalendarYear AS varchar(4)) + '-01-01') 
      ELSE -1 
     END AS Age 
    FROM dimYear  
); 
go 


而最終查詢:

SELECT 
    a.CalendarYear AS "Year" 
    ,a.Age AS "Age" 
    ,count(*) AS "Number Of Lives" 
FROM 
    dbo.People AS p 
    CROSS APPLY dbo.MemberAge(p.DateOfBirth, p.DateLeft) AS a 
WHERE a.Age > 0 
GROUP BY a.CalendarYear, a.Age