两个日期之间的SQL表值用户定义函数
我需要使用两个参数构建一个表值用户定义函数 从func_1'01/01/2012'、'09/09/2015'中选择*等输入 输出应如下所示:两个日期之间的SQL表值用户定义函数,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我需要使用两个参数构建一个表值用户定义函数 从func_1'01/01/2012'、'09/09/2015'中选择*等输入 输出应如下所示: month quator semi_annual annual 1 1 1 2012 2 1 1 2012 3 1 1 2012 4 2 1 2012 5 2 1
month quator semi_annual annual
1 1 1 2012
2 1 1 2012
3 1 1 2012
4 2 1 2012
5 2 1 2012
6 2 1 2012
7 3 2 2012
. . . ...
. . . ....
upto
9 3 2 2015
我需要一个表值函数
我试过这样的代码
create function func3_D_D
(@startDate date, @endDate date)
RETURNS @dates table
(months int,quatorly int,Semi_anuual int,Annual int)
As
Begin
declare
@months int,
@quatorly int,
@Semi_anuual int,
@Annual int;
select @months= DATEDIFF(MONTH, @startDate, @endDate);
select @quatorly= DATEDIFF(QUARTER, @startDate, @endDate);
select @Semi_anuual= DATEDIFF(QUARTER, @startDate, @endDate)/ 2;
select @Annual= DATEDIFF(YEAR, @startDate, @endDate);
WHILE (@endDate > @startDate)
begin
insert into @dates
select @months,@quatorly,@Semi_anuual,@Annual;
End;
return;
End;
使用循环是对性能的一种可怕的影响。你需要用理货台来处理这类事情。你需要开始集中思考,而不是一行一行地思考。一旦你有了一个我用cte生成的理货表,这就很简单了
create function MyFunctionThatGetsDatesByRange
(
@StartDate DATE
, @EndDate DATE
) RETURNS TABLE WITH SCHEMABINDING AS RETURN
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select DATEADD(DAY, N - 1, @StartDate) as date
, DATEPART(MONTH, DATEADD(DAY, N - 1, @StartDate)) as Month
, DATEPART(QUARTER, DATEADD(DAY, N - 1, @StartDate)) as Quarter
, CASE when DATEPART(QUARTER, DATEADD(DAY, N - 1, @StartDate)) <= 2 then 1 else 2 end as SemiAnnual
, DATEPART(YEAR, DATEADD(DAY, N - 1, @StartDate)) as Annual
from cteTally
where N <= DATEDIFF(DAY, @StartDate, @EndDate);
GO
declare @StartDate date = '2012-01-01'
, @EndDate date = '2015-09-09';
select *
from dbo.MyFunctionThatGetsDatesByRange(@StartDate, @EndDate)
您好,谢谢您的回复,我通过使用下面的代码实现了这一点
create function func5_D_D
(@startDate date, @endDate date)
RETURNS @dates table
(months int,
quators int,
semi_annual int,
annual int)
As
Begin
WHILE @startDate <= @endDate
BEGIN
INSERT INTO @dates(months,quators,semi_annual,annual) values (MONTH(@startDate), datepart(qq,@startDate),
case when datepart(qq,@startDate) in (1,2) then 1 else
2 End,datepart(yyyy,@startdate))
SET @startDate = DATEADD(MONTH,1,@startDate)
END
return;
end;
以X年Y月和Z天为单位的两个日期之间的差异,例如:以年、月和天为单位的年龄 我们可以使用下面这样的脚本来获得年、月和日两个日期之间的差异
以X年Y月和Z天为单位的两个日期之间的差异,例如:以年、月和天为单位的年龄 我们可以使用下面这样的脚本来获得两者之间的差异
datDECLARE @FromDate DATETIME = '2010-01-01 23:59:59.000',
@ToDate DATETIME = '2015-01-02 00:00:00.000',
@Years INT, @Months INT, @Days INT, @tmpFromDate DATETIME
SET @Years = DATEDIFF(YEAR, @FromDate, @ToDate)
- (CASE WHEN DATEADD(YEAR, DATEDIFF(YEAR, @FromDate, @ToDate),
@FromDate) > @ToDate THEN 1 ELSE 0 END)
SET @tmpFromDate = DATEADD(YEAR, @Years , @FromDate)
SET @Months = DATEDIFF(MONTH, @tmpFromDate, @ToDate)
- (CASE WHEN DATEADD(MONTH,DATEDIFF(MONTH, @tmpFromDate, @ToDate),
@tmpFromDate) > @ToDate THEN 1 ELSE 0 END)
SET @tmpFromDate = DATEADD(MONTH, @Months , @tmpFromDate)
SET @Days = DATEDIFF(DAY, @tmpFromDate, @ToDate)
- (CASE WHEN DATEADD(DAY, DATEDIFF(DAY, @tmpFromDate, @ToDate),
@tmpFromDate) > @ToDate THEN 1 ELSE 0 END)
SELECT @FromDate FromDate, @ToDate ToDate,
@Years Years, @Months Months, @Days Days
s in Years, Months and days.
你到底试过什么?这不是一个代码生成工厂。这看起来更像是你给我们布置了一个任务,而不是问一个问题。你需要什么帮助?我说的“帮助”是指我们如何帮助您使用您当前尝试的代码以及您将要使用的代码更新您的问题?我提到了我尝试过的代码,我只能看到月份、季度、半年和年度的计数差异,但是我需要像上面提到的那样呈现一张表。无意冒犯,但这只是一种错误的方式。我为您提供了一种基于集合的超快速方法,您又回到了使用循环。在一段代码中有两个是t-sql中最慢的构造。首先是循环,它们效率很低。然后就有了一个多语句表值函数。这些函数甚至比标量函数还要慢。Hi@SeanLange,谢谢你的回答我是SQL初学者,谢谢你的解释,我无法理解你的编码,请你解释一下你在下面的编码中做了什么,以及关于tlaly表,E1N为从值1,1,1,1,1,1,1,1,1dtn中选择1,E2N为从E1 a、E1 b、-10E+2或100行中选择1 E4N为从E2 a、E2 b、-10E+4或10000行中选择1最大cteTallyN为从E4中选择空的订单上选择行数-提前感谢。我使用的是理货表。请阅读本文以获得完整的解释。