首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Server :使用函数计算新列

Server :使用函数计算新列
EN

Stack Overflow用户
提问于 2018-12-20 16:20:14
回答 2查看 840关注 0票数 2

我创建了一个函数,该函数使用日历表计算两个日期之间的工作日数量,以排除假日和周末。

代码语言:javascript
运行
复制
 CREATE FUNCTION dbo.BusinessDays 
     (@sDate SMALLDATETIME, 
      @eDate SMALLDATETIME) 
 RETURNS TABLE 
 AS 
     RETURN (SELECT COUNT(*) dt 
             FROM dbo.Calendar 
             WHERE dt BETWEEN @sDate AND @eDate) 
Go

我的问题是:如何使用这个函数从另一个有两个日期列的表(dbo.HolidayRequestForm)中计算列?

我试过了

代码语言:javascript
运行
复制
ALTER TABLE Test
    ADD HoursTaken AS dbo.BusinessDays ([StartDate], [FinishDate])
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-12-20 17:06:37

我认为最好的做法是重构函数以返回标量值:

代码语言:javascript
运行
复制
CREATE FUNCTION dbo.BusinessDays
(
    @sDate SMALLDATETIME,
    @eDate SMALLDATETIME
)
RETURNS INT
AS
BEGIN
    DECLARE @RTN INT;

    SELECT @RTN = COUNT(*) 
    FROM dbo.Calendar
    WHERE dt BETWEEN @sDate AND @eDate;

    RETURN @RTN;
END

然后添加计算列的SQL将保持不变。

如果您的函数需要保留为表值函数,则需要使用CROSS APPLY

代码语言:javascript
运行
复制
SELECT * 
FROM dbo.HolidayRequestForm
    CROSS APPLY dbo.BusinessDays(StartDate, FinishDate) d

正如您所看到的,这会使使用计算列变得相当棘手。

几个不相关的观点:

  • 我不确定HoursTaken是否是计算列的最佳名称,因为它似乎在存储两个日期之间的天数(而不是小时)。
  • 在查询中使用日期范围时,最好使用WHERE DateColumn >= @DateStart AND DateColumn < @EndDate。有关更多信息,请参见这篇博客文章
票数 1
EN

Stack Overflow用户

发布于 2018-12-20 19:51:39

想要使用内联(纯) to函数是正确的。Server中有两种类型的Table函数:内联表值函数和错误函数.不幸的是,您不能为计算列使用内联表值函数,而且,如果性能非常重要,不希望对计算列使用T标量UDF。

好消息是你不需要这么做。你有几个选择。首先,不需要日历表来计算工作日,您可以将此逻辑用于计算列:

代码语言:javascript
运行
复制
CASE WHEN SIGN(DATEDIFF(dd, @startDate, @endDate)) > -1 THEN
                (DATEDIFF(dd, @startDate, @endDate) + 1) --total days including weekends
               -(DATEDIFF(wk, @startDate, @endDate) * 2) --Subtact 2 days for each full weekend
    -- Subtract 1 when startDate is Sunday and Substract 1 when endDate is Sunday: 
    -(CASE WHEN DATENAME(dw, @startDate) = 'Sunday'   THEN 1 ELSE 0 END)
    -(CASE WHEN DATENAME(dw, @endDate)   = 'Saturday' THEN 1 ELSE 0 END)

您还可以使用此逻辑创建索引视图,该视图更灵活,也可能是更好的选择。

下面有几个很好的链接,说明为什么您从不使用T标量UDF作为计算列或约束:

具有(标量udf)的计算列可能影响查询性能。 -Kun Cheng (SQLCAT)

另一个隐藏的并行性杀手:检查约束中的标量UDF - Erik (本文也适用于计算列)

计算列中标量函数不是一个好主意的另一个原因。 - Erik Darling

对调用UDF的约束要小心 - Tibor Karaszi

小心.行-行-操作.udf-服装 - Brian

为什么执行计划包括对持久化计算列的标量udf调用? -堆栈溢出

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53872407

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档