作成しようとしている T-SQL 関数について何か助けが得られるかどうか疑問に思っていました。
クエリが必要なサンプル データを次に示します。
簡略化された表:
ID|PersonID|ValueTypeID|ValueTypeDescription|Value
1|ZZZZZ000L6|ZZZZZ00071|Start Prison Date|3/28/2012
2|ZZZZZ000L6|ZZZZZ00071|Start Prison Date|10/10/2012
3|ZZZZZ000L6|ZZZZZ00072|End Prison Date |3/29/2012
4|ZZZZZ000MD|ZZZZZ00071|Start Prison Date|1/15/2012
5|ZZZZZ000MD|ZZZZZ00072|End Prison Date |2/15/2012
6|ZZZZZ000MD|ZZZZZ00071|Start Prison Date|4/1/2012
7|ZZZZZ000MD|ZZZZZ00072|End Prison Date |4/5/2012
8|ZZZZZ000MD|ZZZZZ00071|Start Prison Date|9/3/2012
9|ZZZZZ000MD|ZZZZZ00072|End Prison Date |12/1/2012
私が必要としているのは、PersonID
と Year ( @PID, @YR
) を受け取り、その年にその人が刑務所にいた日数を返す T-SQL 関数です。
dbo.NumDaysInPrison(@PID, @YR) as int
例:
dbo.NumDaysInPrison('ZZZZZ000L6', 2012) returns 84
dbo.NumDaysInPrison('ZZZZZ000MD', 2012) returns 124
これまでのところ、時々答えが得られるこのクエリを思いつきました。
DECLARE @Year int
DECLARE @PersonID nvarchar(50)
SET @Year = 2012
SET @PersonID = 'ZZZZZ000AA'
;WITH StartDates AS
(
SELECT
Value,
ROW_NUMBER() OVER(ORDER BY Value) AS RowNumber
FROM Prisoners
WHERE ValueTypeDescription = 'Start Prison Date' AND PersonID = @PersonID AND YEAR(Value) = @Year
), EndDates AS
(
SELECT
Value,
ROW_NUMBER() OVER(ORDER BY Value) AS RowNumber
FROM Prisoners
WHERE ValueTypeDescription = 'End Prison Date' AND PersonID = @PersonID AND YEAR(Value) = @Year
)
SELECT
SUM(DATEDIFF(d, s.Value, ISNULL(e.Value, cast(str(@Year*10000+12*100+31) as date)))) AS NumDays
FROM StartDates s
LEFT OUTER JOIN EndDates e ON s.RowNumber = e.RowNumber
これは、年の初めのレコードが終了日なしで残されている場合、キャプチャに失敗します。たとえば、個人のレコードが 2 つしかない場合:
ID|PersonID|ValueTypeID|ValueTypeDescription|Value
1|ZZZZZ000AA|ZZZZZ00071|Start Prison Date|3/28/2012
2|ZZZZZ000AA|ZZZZZ00071|Start Prison Date|10/10/2012
(2012/3/28 -> 年末) (2012/10/10 -> 年末)
278 ではなく 360 を返します。