交叉应用于标量值和 table 值函数

Cross apply on both scalar-valued and table-valued functions

我的存储过程使用交叉应用到 运行 select 中的几个函数。其中 3 个函数是标量值,而最后一个是 table 值。

ALTER PROCEDURE [dbo].[GetThreadsInArea] 
    @CountryCode nvarchar(10),
    @Latitude float,
    @Longtitude float,
    @DistanceInKm int,
    @Offset int,
    @UserID int
AS
BEGIN
SELECT t.ID, t.[Date], t.[Text], t.Points, func.Distance, func.Messages, t.Color, func.IsOwnThread, func.HasVotedIsUpvote
FROM dbo.Threads as t
    CROSS APPLY
    ( Select
        dbo.fnCalcDistanceKM(t.Latitude, @Latitude, t.Longtitude, @Longtitude) as Distance, -- Scalar-valued
        dbo.GetThreadCommentCount(t.ID) as [Messages], -- Scalar-valued
        dbo.IsOwnThread(t.ID, @UserID) as IsOwnThread, -- Scalar-valued
        dbo.HasVotedIsUpvote(t.ID, @UserID) as HasVotedIsUpvote -- Table-valued
    ) as func
WHERE t.CountryCode = @CountryCode AND func.Distance < @DistanceInKm
ORDER BY t.Date desc
OFFSET @Offset ROWS
FETCH NEXT 20 ROWS ONLY
END

这个命令完成得很好,但是当我尝试 运行 执行它时,我得到:

Msg 4121, Level 16, State 1, Procedure dbo.GetThreadsInArea, Line 10 [Batch Start Line 0]
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.HasVotedIsUpvote", or the name is ambiguous.

(1 row(s) affected)

受影响的第 1 行也让我感到困惑。存储过程不应更改任何行上的任何数据。是从 table 值函数返回的行受到影响吗?

编辑:

这就是程序现在的样子,尽管我不喜欢在 SELECT 和 WHERE 中使用 dbo.fnCalcDistanceKM 两次。有什么解决办法吗?

ALTER PROCEDURE [dbo].[GetThreadsInArea] 
    @CountryCode nvarchar(10),
    @Latitude float,
    @Longtitude float,
    @DistanceInKm int,
    @Offset int,
    @UserID int
AS
BEGIN
SELECT t.ID,
       t.[Date],
       t.[Text],
       t.Points,
       **dbo.Fncalcdistancekm(t.Latitude, @Latitude, t.Longtitude, @Longtitude)** AS Distance,
       dbo.Getthreadcommentcount(t.ID) AS [Messages],
       t.Color,
       dbo.Isownthread(t.ID, @UserID) AS IsOwnThread,
       func.HasVoted,
       func.IsUpvote
FROM   dbo.Threads AS t
       CROSS APPLY dbo.Hasvotedisupvote(t.ID, @UserID) func
WHERE  t.CountryCode = @CountryCode
       AND **dbo.Fncalcdistancekm(t.Latitude, @Latitude, t.Longtitude, @Longtitude)** < @DistanceInKm
ORDER  BY t.Date DESC
OFFSET @Offset ROWS
FETCH NEXT 20 ROWS ONLY
END

我尝试使用它的别名 Distance,但它只告诉我:

Msg 207, Level 16, State 1, Procedure GetThreadsInArea, Line 22 [Batch Start Line 7]
Invalid column name 'Distance'.

为什么要将 scalar 函数放在 cross apply 中,只需在 Select 中使用它,而在 cross apply 中单独使用 table 值函数。像这样

SELECT t.ID,
       t.[Date],
       t.[Text],
       t.Points,
       dbo.Fncalcdistancekm(t.Latitude, @Latitude, t.Longtitude, @Longtitude) AS Distance,
       dbo.Getthreadcommentcount(t.ID)                                        AS [Messages],
       t.Color,
       dbo.Isownthread(t.ID, @UserID)                                         AS IsOwnThread,
       func.HasVoted,
       func.IsUpvote
FROM   dbo.Threads AS t
       CROSS APPLY dbo.Hasvotedisupvote(t.ID, @UserID) func
WHERE  t.CountryCode = @CountryCode
       AND dbo.Fncalcdistancekm(t.Latitude, @Latitude, t.Longtitude, @Longtitude) < @DistanceInKm
ORDER  BY t.Date DESC
OFFSET @Offset ROWS FETCH NEXT 20 ROWS ONLY 

关于 (1 行受影响) 您是否启用了执行计划?

如果您不想两次使用该函数,那么您可以使用派生的 table 或在 CROSS APPLY

中单独使用该函数
SELECT t.ID,
       t.[Date],
       t.[Text],
       t.Points,
       cs.Distance,
       dbo.Getthreadcommentcount(t.ID)                                        AS [Messages],
       t.Color,
       dbo.Isownthread(t.ID, @UserID)                                         AS IsOwnThread,
       func.HasVoted,
       func.IsUpvote
FROM   dbo.Threads AS t
       CROSS APPLY dbo.Hasvotedisupvote(t.ID, @UserID) func
       cross apply (select dbo.Fncalcdistancekm(t.Latitude, @Latitude, t.Longtitude, @Longtitude))cs (Distance)
WHERE  t.CountryCode = @CountryCode
       AND cs.Distance < @DistanceInKm
ORDER  BY t.Date DESC
OFFSET @Offset ROWS FETCH NEXT 20 ROWS ONLY