SQL Server:交叉应用使列可为空



我正在制作一个视图,但我有点困惑为什么我的字段被转换为可为空。我正在使用SQL Server 2016。

CREATE OR ALTER VIEW [dbo].[vwEmployeePTORequest]
AS
    SELECT 
        Employees.EmployeeID, Employees.DivisionID,
        PTORequests.PTORequestId, PTORequests.IsPaidOut,
        PTORequests.PayoutPayEntryEarningId,
        --Why do I have to use ISNULL here?
        ISNULL(SummaryDetails.TotalHours, 0) AS TotalHours,
        SummaryDetails.RequestStartDate, SummaryDetails.RequestEndDate,
        SummaryDetails.DivisionPTOAccrualId
    FROM 
        dbo.Employees
    INNER JOIN  
        dbo.GlobalIds ON Employees.GlobalId = GlobalIds.Id
    INNER JOIN 
        dbo.Activities ON Activities.OriginatorGlobalId = GlobalIds.Id
    INNER JOIN 
        dbo.PTORequests ON Activities.ActivityId = PTORequests.ActivityId
    CROSS APPLY 
        dbo.GetEmployeePTORequestDetailSummary(PTORequests.PTORequestId) AS SummaryDetails;

这是在CROSS APPLY中调用的函数:

CREATE OR ALTER FUNCTION [dbo].[GetEmployeePTORequestDetailSummary]
    (@PTORequestId INT)
RETURNS TABLE
AS
    RETURN
        (SELECT TOP 1 
             SUM(Hours) AS TotalHours,
             MIN(RequestDate) AS RequestStartDate,
             MAX(RequestDate) AS RequestEndDate,
             DivisionPTOAccrualId AS DivisionPTOAccrualId
         FROM 
             dbo.PTORequestDetails  
         WHERE 
             PTORequestId = @PTORequestId
         GROUP BY 
             PTORequestId, DivisionPTOAccrualId);

这是表定义的相关部分:

CREATE TABLE [dbo].[PTORequestDetails]
(
    [PTORequestDetailId] [int] IDENTITY(1,1) NOT NULL,
    [RequestDate] [date] NOT NULL,
    [StartTime] [datetime] NULL,
    [Hours] [decimal](19, 2) NOT NULL,
)

我对为什么会发生这种情况有点困惑。如您所见,我的列不可为 NULL,聚合函数返回不可为空的类型,并且我正在使用类似于内部连接的每行工作的CROSS APPLY。 由于它是一对一的,因此不应创建可为空的。

谁能解释为什么我的列显示为可为空,以及如何在函数中解决此问题,以便使用它的所有其他过程不必为每个选定的列指定ISNULL()条件?

这不是交叉应用。它是聚合函数。SUM、MIN、MAX 都假定为可为空,因为如果您在没有 GROUP BY 的空表上使用它们,它们将返回 NULL。

此外,如果使用某些已弃用的会话选项,SUM 可以返回 NULL 而不是整数溢出错误。

因此,您需要将聚合包装在ISNULL中,以使列被视为不可为空。

最新更新