在表值函数中使用CTE的问题

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开发人员,所以我可能在上面的代码中有一些明显的错误.但是,我很困惑,为什么它不起作用.

提前致谢.

Mik*_*son 5

没有经过测试,但这样的事情应该做你想要的.

   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.

顺便说一句:你所做的是你Jobnumbercase声明中检查CTE 中的存在.如果CTE中没有行,您最终进入else部分,但由于您在主查询Jobnumberfrom子句中使用CTE ,因此您不会获得任何行,因为CTE Jobnumber未返回任何行.

所以要完全清楚发生了什么.case如果CTE中没有行,则永远不会执行该语句Jobnumber.