Sql server 如何在sql中对循环中的函数求和?

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

我们有一个函数,它接收4个变量并返回一个int结果。 我们希望对表中的每条记录使用此函数,而这4个变量取自每条记录

我该如何解决它

我的职能:

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下单