bob*_*bbo 0 sql t-sql sql-server-2005 sql-server-2008
我试图避免在我的项目中使用标量值函数,所以我决定尝试使用CTE将其中一个转换为表值函数.
我知道标量值函数的性能很差,因为它们必须为每一行执行,而SQL服务器无法以任何方式对其进行优化(即它充当黑盒子).
这是我第一次尝试将其转换为表值函数...
CREATE FUNCTION [dbo].[fn_get_job_average] (@jobnumber VARCHAR(50))
RETURNS TABLE AS RETURN
(
WITH JobAverage AS
(
SELECT job.Jobnumber, CAST(AVG(CAST(jobMark.Mark AS DECIMAL(18,1))) AS DECIMAL(18,1)) AS Average
FROM job
INNER JOIN jobMark
ON job.Guid = jobMark.Guid
WHERE job.Jobnumber = @jobnumber
GROUP BY job.Jobnumber
)
SELECT Jobnumber,
CASE
WHEN EXISTS(SELECT * FROM JobAverage) THEN Average
ELSE 0.0 -- This never executes???, i.e. for job records that don't have a mark nothing is returned
END AS Average
FROM JobAverage
)
Run Code Online (Sandbox Code Playgroud)
我想输出一个包含工号和平均分数的表格.
对于有标记的工作,似乎没问题.也就是说,平均值与jobnumer一起返回.
对于没有商标的工作,似乎出错了.语句的ELSE部分不执行.也就是说,作为平均工作,我不会返回0.0.没有记录返回.我错过了什么吗?
对不起,我不是一个经验丰富的SQL开发人员,所以我可能在上面的代码中有一些明显的错误.但是,我很困惑,为什么它不起作用.
提前致谢.
没有经过测试,但这样的事情应该做你想要的.
SELECT job.Jobnumber, COALESCE(CAST(AVG(CAST(jobMark.Mark AS DECIMAL(18,1))) AS DECIMAL(18,1)), 0.0) AS Average
FROM job
LEFT OUTER JOIN jobMark
ON job.Guid = jobMark.Guid
WHERE job.Jobnumber = @jobnumber
GROUP BY job.Jobnumber
Run Code Online (Sandbox Code Playgroud)
无需使用CTE.
顺便说一句:你所做的是你Jobnumber
在case
声明中检查CTE 中的存在.如果CTE中没有行,您将最终进入else部分,但由于您在主查询Jobnumber
的from
子句中使用CTE ,因此您不会获得任何行,因为CTE Jobnumber
未返回任何行.
所以要完全清楚发生了什么.case
如果CTE中没有行,则永远不会执行该语句Jobnumber
.