使用临时表

时间:2015-10-20 11:16:21

标签: sql sql-server recursion user-defined-functions

我有以下函数循环遍历树结构以查看是否有任何子注释包含属性:

CREATE FUNCTION [dbo].[ufn_FamilyHasCar] ( @PersonId Integer ) RETURNS bit
as
BEGIN
    DECLARE @Out bit = 0
    Declare @Count int
    Select @Count = count(*) from car WHERE owner_id = @PersonId and type = 2
    if @Count = 0
        begin 
            declare @tbl_temp table (personId int)
            Declare @Id int
            insert into @tbl_temp(personId) (select id from person where parent_id = @PersonId) 
            While (Select Count(*) From @tbl_temp) > 0
                Begin
                    Select Top 1 @Id = personId From @tbl_temp
                    set @Out = dbo.ufn_FamilyHasCar(@Id)
                    if @Out = 1
                        break
                    Delete from @tbl_temp Where personId = @Id
                End
        end
    else 
    set @Out = 1
RETURN @Out
END
GO

这似乎是我目前实施的瓶颈,所以我问是否以及如何改善udf的性能?

1 个答案:

答案 0 :(得分:1)

我会用递归CTE替换它:

with pp as (
      select p.id
      from person p
      where p.id = @personid
      union all
      select p.id
      from pp join
           person p
           on pp.parentid = p.id
    )
select (case when count(*) > 0 then 1 else 0 end)
from pp join
     car c
     on pp.id = c.owner_id and type = 2;

COUNT(*)是表达查询的最清晰方式。但是,如果有很多匹配(比如说多于几十个),那么聚合的额外开销就是过度的,你可以使用exists代替:

with pp as ( . . .)
select (case when exists (select 1 from pp join car cc on pp.id = c.owner_id and type = 2)
             then 1 else 0
        end);