我正在SQL Server 2012中编写一个函数,该函数需要知道自给定日期以来已过去的3个特定日期的数量。我可以用一个while循环来做这个,但它很慢,我正在寻找一个更好的方法。 以下是我到目前为止的情况:
我们假设GETDATE()= '11 / 14/2016'和@productDate = '10 / 1/2016'
--Get the number of "units" that have passed since the date on the label
DECLARE @unitCount INT = 0;
DECLARE @countingDate DATE
SET @countingDate = DATEADD(DAY,1,@productDate);--add 1 to prevent counting the date on the label as the first unit
WHILE (@countingDate < CAST(GETDATE() As date ))
BEGIN
SELECT @unitCount = @unitCount +
CASE
WHEN DAY(@countingDate) = 1 OR DAY(@countingDate) = 10 OR DAY(@countingDate) = 20 THEN 1
ELSE 0
END
SET @countingDate = DATEADD(DAY,1,@countingDate);
END
这将导致@unitCount = 4
<11> '11 / 20/2016'的GETDATE()将导致@unitCount = 5
答案 0 :(得分:2)
不使用数字表
create function dbo.fn_DateCounter
(
@datefrom date,
@dateto date
)
returns int
as
begin
return
-- number of complete months
3 *
(
(DATEPART(YYYY, @dateto) * 12 + DATEPART(MM, @dateto))
-(DATEPART(YYYY, @datefrom) * 12 + DATEPART(MM, @datefrom))
- 1
)
-- add on the extras from the first month
+ case when DATEPART(DD, @datefrom) < 10 then 2
when DATEPART(DD, @datefrom) < 20 then 1
else 0
end
-- add on the extras from the last month
+ case when DATEPART(DD, @dateto) > 20 then 3
when DATEPART(DD, @dateto) > 10 then 2
else 1
end
end
go
select dbo.fn_DateCounter('01-jan-2000','01-jan-2000') -- 0
select dbo.fn_DateCounter('01-jan-2000','10-jan-2000') -- 0
select dbo.fn_DateCounter('01-jan-2000','11-jan-2000') -- 1
select dbo.fn_DateCounter('01-jan-2000','20-jan-2000') -- 1
select dbo.fn_DateCounter('01-jan-2000','21-jan-2000') -- 2
select dbo.fn_DateCounter('11-jan-2000','21-jan-2000') -- 1
select dbo.fn_DateCounter('11-jan-2000','21-feb-2000') -- 4
select dbo.fn_DateCounter('01-jan-2000','01-jan-2001') -- 36
select dbo.fn_DateCounter('01-jan-2000','11-jan-2001') -- 37
答案 1 :(得分:1)
您可以结合使用sum
,case
和dbo.spt_values
表:
declare @productDate datetime = '11/01/2016',
@unitCount int
;with nums as ( -- use a CTE to build a number list
select top 1000 number from master..spt_values
)
select @unitCount = sum(
case when day(dateadd(day, n, @productDate)) in (1, 10, 20)
then 1 else 0 end
) -- add 1 for each 1,10,20 we find
from (
select n = row_number() over (order by nums.number)
from nums cross join nums as num -- 1000*1000 = 1 million rows
) n
where dateadd(day, n, @productDate) < getdate()
select @unitCount
这将获取@productDate
和getdate()
之间的每个日期。对于每1/10/20,case
语句将select 1
,对于每个其他日期,{0}将为0。最后,我们取结果的sum
。
对于11/1 - 11/11
,它返回1。
对于1/1 - 11/11
,结果为31。
编辑:在CTE(with nums as...
)中,我们选择1-1000
,然后我们执行cross join
,这为我们提供了一百万条记录。答案仍然有限,但现在你可以用2700年了。