我的存储过程使用交叉应用来运行select中的几个函数。其中3个函数是标量值,而最后一个函数是表值。
YES
这个命令完成得很好,但是当我尝试运行它时,我得到:
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
受影响的第一行也让我感到困惑。存储过程不应更改任何行上的任何数据。它是从受影响的表值函数返回的行吗?
修改
所以这就是程序现在的样子,尽管我不喜欢在SELECT和WHERE中使用dbo.fnCalcDistanceKM两次。对此有何解决方案?
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)
我尝试使用别名Distance,但它只是告诉我:
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
答案 0 :(得分:2)
为什么要将scalar
函数放在cross apply
中,只需在Select
中使用它,并在cross apply
中单独使用表值函数。像这样的东西
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行)您是否启用了执行计划?
如果您不想两次使用该功能,则可以使用派生表或在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