Sql server 如何在sql中对循环中的函数求和?
我们有一个函数,它接收4个变量并返回一个int结果。 我们希望对表中的每条记录使用此函数,而这4个变量取自每条记录 我该如何解决它 我的职能:Sql server 如何在sql中对循环中的函数求和?,sql-server,tsql,stored-functions,Sql Server,Tsql,Stored Functions,我们有一个函数,它接收4个变量并返回一个int结果。 我们希望对表中的每条记录使用此函数,而这4个变量取自每条记录 我该如何解决它 我的职能: CREATE FUNCTION dbo.occupiedDaysPerListingFunction(@CheckIn date, @CheckOut date, @Email varchar(80), @Title varchar(50)) RETURNS int AS BEGIN DECLARE @ni
CREATE FUNCTION dbo.occupiedDaysPerListingFunction(@CheckIn date, @CheckOut date, @Email varchar(80), @Title varchar(50))
RETURNS int
AS
BEGIN
DECLARE @nightsInRange int
select @nightsInRange= (CASE
WHEN DATEDIFF(day,@CheckIn,getdate()) >0 and DATEDIFF(day,@CheckOut,getdate())+100 <0 THEN 100
WHEN DATEDIFF(day,@CheckIn,getdate()) >0 and DATEDIFF(day,@CheckOut,getdate())+100 >0 THEN DATEDIFF(day,getdate(),@CheckOut)
WHEN DATEDIFF(day,getdate(),@CheckIn) >0 and DATEDIFF(day,getdate(),@CheckIn) <100 and DATEDIFF(day,@CheckOut,getdate())+100 >0 THEN DATEDIFF(day,@CheckIn,@CheckOut)
WHEN DATEDIFF(day,getdate(),@CheckIn) >0 and DATEDIFF(day,getdate(),@CheckIn) <100 and DATEDIFF(day,@CheckOut,getdate())+100 <0 THEN DATEDIFF(day,@CheckIn,getdate())+100
WHEN DATEDIFF(day,@CheckIn,getdate()) <0 THEN 0
END)
FROM [dbo].[ORDERS] o
WHERE o.[E-mail] = @Email and o.[title]=@Title
RETURN @nightsInRange
end
创建函数dbo.occupiedDaysPerListingFunction(@CheckIn-date、@CheckOut-date、@Email-varchar(80)、@Title-varchar(50))
返回整数
作为
开始
声明@nightsInRange int
选择@nightsInRange=(大小写)
当DATEDIFF(day,@CheckIn,getdate())>0和DATEDIFF(day,@CheckOut,getdate())+100 0和DATEDIFF(day,@CheckOut,getdate())+100>0时,则为DATEDIFF(day,getdate(),@CheckOut)
当DATEDIFF(day,getdate(),@CheckIn)>0且DATEDIFF(day,getdate(),@CheckIn)为0时,则为DATEDIFF(day,@CheckIn,@CheckOut)
当DATEDIFF(day,getdate(),@CheckIn)>0和DATEDIFF(day,getdate(),@CheckIn)光标仅适用于此任务时。Сursor是可能的选项之一。您还可以使用WHILE循环、CTE等
DECLARE @iterator CURSOR
DECLARE @bufferTable TABLE
(
CheckIn date,
CheckOut date,
Email varchar(80),
Title varchar(50)
)
SET @iterator = CURSOR FOR
SELECT
CheckIn,
CheckOut,
Email,
Title
FROM [YourDatabase].[YourSchema].[YourTable]
OPEN @iterator
FETCH NEXT FROM @iterator
INTO @bufferTable
WHILE @@FETCH_STATUS = 0
BEGIN
/* Your function comes into play */
dbo.occupiedDaysPerListingFunction(@bufferTable.CheckIn, @bufferTable.CheckOut, @bufferTable.Email, @bufferTable.Title)
FETCH NEXT FROM @iterator
INTO @bufferTable
END;
CLOSE @iterator
DEALLOCATE @iterator
GO
编辑:
根据@的回答,您可以缩小SELECT查询的范围,如下所示:
SELECT InnerQueryTable.OccupiedDaysPerListing FROM
(
SELECT
CheckInDate,
CheckOutDate,
Email,
Title,
dbo.occupiedDaysPerListingFunction(CheckInDate, CheckOutDate, Email, Title) AS OccupiedDaysPerListing
FROM
[YourDatabase].[YourSchema].[YourTable]
) AS InnerQueryTable
GO
CREATE FUNCTION dbo.occupiedDaysPerListingFunction(@CheckIn DATE, @CheckOut
DATE, @Email VARCHAR(80), @Title VARCHAR(50))
RETURNS INT
AS
BEGIN
DECLARE @nightsInRange INT = 0;
SET @nightsInRange = (SELECT TOP 1 CASE
WHEN DATEDIFF(day,@CheckIn,getdate()) >0 and DATEDIFF(day,@CheckOut,getdate())+100 <0 THEN 100
WHEN DATEDIFF(day,@CheckIn,getdate()) >0 and DATEDIFF(day,@CheckOut,getdate())+100 >0 THEN DATEDIFF(day,getdate(),@CheckOut)
WHEN DATEDIFF(day,getdate(),@CheckIn) >0 and DATEDIFF(day,getdate(),@CheckIn) <100 and DATEDIFF(day,@CheckOut,getdate())+100 >0 THEN DATEDIFF(day,@CheckIn,@CheckOut)
WHEN DATEDIFF(day,getdate(),@CheckIn) >0 and DATEDIFF(day,getdate(),@CheckIn) <100 and DATEDIFF(day,@CheckOut,getdate())+100 <0 THEN DATEDIFF(day,@CheckIn,getdate())+100
WHEN DATEDIFF(day,@CheckIn,getdate()) <0 THEN 0
ELSE 0
END
FROM [dbo].[ORDERS] o
WHERE o.[E-mail] = @Email and o.[title]=@Title)
RETURN @nightsInRange
END
SELECT
CheckInDate,
CheckOutDate,
Email,
Title,
dbo.occupiedDaysPerListingFunction(CheckInDate, CheckOutDate, Email, Title) AS OccupiedDaysPerListing
FROM
[YourDatabase].[YourSchema].[YourTable]
<>我将开始确保你的函数总是返回一个整数。你当前的函数用电子邮件和标题的一个过滤器向你的[订单]表发送一个查询。你应该考虑如果你的[订单]表包含多个具有相同电子邮件和标题的行,将会发生什么。
首先,我将重写函数,如下所示:
SELECT InnerQueryTable.OccupiedDaysPerListing FROM
(
SELECT
CheckInDate,
CheckOutDate,
Email,
Title,
dbo.occupiedDaysPerListingFunction(CheckInDate, CheckOutDate, Email, Title) AS OccupiedDaysPerListing
FROM
[YourDatabase].[YourSchema].[YourTable]
) AS InnerQueryTable
GO
CREATE FUNCTION dbo.occupiedDaysPerListingFunction(@CheckIn DATE, @CheckOut
DATE, @Email VARCHAR(80), @Title VARCHAR(50))
RETURNS INT
AS
BEGIN
DECLARE @nightsInRange INT = 0;
SET @nightsInRange = (SELECT TOP 1 CASE
WHEN DATEDIFF(day,@CheckIn,getdate()) >0 and DATEDIFF(day,@CheckOut,getdate())+100 <0 THEN 100
WHEN DATEDIFF(day,@CheckIn,getdate()) >0 and DATEDIFF(day,@CheckOut,getdate())+100 >0 THEN DATEDIFF(day,getdate(),@CheckOut)
WHEN DATEDIFF(day,getdate(),@CheckIn) >0 and DATEDIFF(day,getdate(),@CheckIn) <100 and DATEDIFF(day,@CheckOut,getdate())+100 >0 THEN DATEDIFF(day,@CheckIn,@CheckOut)
WHEN DATEDIFF(day,getdate(),@CheckIn) >0 and DATEDIFF(day,getdate(),@CheckIn) <100 and DATEDIFF(day,@CheckOut,getdate())+100 <0 THEN DATEDIFF(day,@CheckIn,getdate())+100
WHEN DATEDIFF(day,@CheckIn,getdate()) <0 THEN 0
ELSE 0
END
FROM [dbo].[ORDERS] o
WHERE o.[E-mail] = @Email and o.[title]=@Title)
RETURN @nightsInRange
END
SELECT
CheckInDate,
CheckOutDate,
Email,
Title,
dbo.occupiedDaysPerListingFunction(CheckInDate, CheckOutDate, Email, Title) AS OccupiedDaysPerListing
FROM
[YourDatabase].[YourSchema].[YourTable]
希望这能有所帮助。问题的标题提到了“sum”,但这并没有出现在问题中。为什么不呢?一般来说,TOP
应该与ORDER BY
配对。在这种情况下,任何行都可以,值得添加一条注释来解释预期的行为。请注意,GetDate()的每个实例
将为所有行返回单个值,但不同的实例可能返回不同的值。最佳做法是获取单个值,例如将@Now声明为DateTime=GetDate();
,并在函数的其余部分使用变量@Now
。同意您的观点,@HABO。这将是查询的额外改进。在这种情况下,他很可能希望按OrderDate降序。即按[OrderDate]DESC下单