在 CTE 中实现标量函数

Posted

技术标签:

【中文标题】在 CTE 中实现标量函数【英文标题】:Implement the Scalar Function inside a CTE 【发布时间】:2019-08-16 06:57:04 【问题描述】:

我有一个视图(视图中包含一个 CTE,如下所示),其中我调用了一个标量函数,而在同一个标​​量函数中调用了视图。这整个过程使性能变慢。我可以在同一个视图中实现函数的功能吗? 请帮忙

WITH tree AS
(
    SELECT c1.structureid,c1.assessmentid, c1.sequence,c1.Required,c1.Objective,  c1.parentid, c1.Text, [level] = 1, path = cast( c1.structureid as varchar(100))

FROM [ast].[Structure] c1
WHERE c1.parentid IS NULL 
UNION ALL
SELECT c2.structureid, c2.assessmentid, c2.sequence,c2.Required,c2.Objective,   c2.parentid, c2.Text, [level] = tree.[level] + 1, 
       Path = Cast(tree.path+'/'+right('000000000' + cast(c2.structureid as varchar(10)),10) as varchar(100))

FROM [ast].[Structure] c2 INNER JOIN tree ON tree.structureid = c2.parentid
)
SELECT tree.level,tree.sequence,
tree.path, parentid, tree.assessmentid, tree.Required,tree.Objective, (SELECT [dbo].Tree_full_index(tree.structureid))+' '+ tree.Text AS description ,C.* ,
wasScored = (case when C.choiceid is null then 0 else 1 end ),
wasDerived = (case when C.choiceid is null and C.Score is not null then 1 else 0 end )
FROM tree inner join [ast].[Value] as C on tree.structureid = C.structureid 

标量函数

ALTER FUNCTION [dbo].[Tree_full_index]
(

    @tree_node_id int
)
RETURNS varchar(20)
AS
BEGIN

    declare @result varchar(20)
    set @result =''
    declare @node_seq_index varchar(5)  

    DECLARE @parentID int

    select @node_seq_index=isnull(sequence,''),@parentID=isnull(parentid,0) from vwAssesment where structureid=@tree_node_id


    set @result=@node_seq_index

      WHILE @parentID > 0
        BEGIN
          SELECT @tree_node_id = @parentID
          select @node_seq_index=isnull(sequence,''),@parentID=parentid from vwAssesment where structureid=@tree_node_id


            set @result=@node_seq_index+'.0'+@result
        END
      RETURN @result

END

结构表

StructureId AssessmentId    ParentId    Required    Sequence    Text    Objective
633 132 NULL    1   1   Customer Satisfaction   understand our top Customers and our supplier ranking with them.
634 132 633 1   1   Top Customers   NULL
635 132 634 1   1   Display top Customers on Lead Board NULL
636 132 634 1   2   Display Customer Supplier Ranking for Facility - NA NULL
637 132 634 1   3   Display Work Plan that provides path to Preferred Supplier status   NULL
638 132 633 1   2   Real Time Response Process  NULL
639 132 638 0   1   Real-time response system in place when abnormalities occur with documented Counter Measures    NULL
640 132 NULL    1   2   Continuous Improvement  ensure driving foundation for Continuous Improvement 
641 132 640 1   1   Gemba   NULL
642 132 641 1   1   Routine and scheduled   NULL
643 132 641 1   2   Incorporated into appropriate different levels of organization  NULL
644 132 640 1   2   TPM NULL
645 132 644 1   1   Perform initial Cleaning & Inspection (Level 1) NULL
646 132 645 1   1   Learn how to identify equipment problems    NULL

结果应该有如图所示的节点实际索引的列

level   sequence    parentid    assessmentid    Required    Objective   description ValueId InstanceId  StructureId ChoiceId    Score   wasScored   wasDerived
1   1   NULL    132 1   understand our top Customers and our supplier ranking with them.  Ensure In-Station Quality and continuous improvement. 1 Customer Satisfaction 666 207 633 NULL    2   0   1
2   1   633 132 1   NULL    1.01 Top Customers  667 207 634 NULL    4   0   1
3   1   634 132 1   NULL    1.01.01 Display top Customers on Lead Board 668 207 635 40  4   1   0
3   2   634 132 1   NULL    1.01.02 Display Customer Supplier Ranking for Facility - NA 669 207 636 40  4   1   0
3   3   634 132 1   NULL    1.01.03 Display Work Plan that provides path to Preferred Supplier status   670 207 637 40  4   1   0
2   2   633 132 1   NULL    1.02 Real Time Response Process 671 207 638 NULL    NULL    0   0
3   1   638 132 0   NULL    1.02.01 Real-time response system in place when abnormalities occur with documented Counter Measures    672 207 639 NULL    NULL    0   0
1   2   NULL    132 1   ensure driving foundation for Continuous Improvement culture to be successful and achieve meaningful results    2 Continuous Improvement    673 207 640 NULL    3.5 0   1
2   1   640 132 1   NULL    2.01 Gemba  674 207 641 20  2   1   0
3   1   641 132 1   NULL    2.01.01 Routine and scheduled   675 207 642 NULL    NULL    0   0
3   2   641 132 1   NULL    2.01.02 Incorporated into appropriate different levels of organization (Facility Manager, Staff, site Director) 676 207 643 NULL    NULL    0   0
2   2   640 132 1   NULL    2.02 TPM    677 207 644 NULL    5   0   1
3   1   644 132 1   NULL    2.02.01 Perform initial Cleaning & Inspection (Level 1) 678 207 645 50  5   1   0
4   1   645 132 1   NULL    2.02.01.01 Learn how to identify equipment problems 679 207 646 NULL    NULL    0   0

【问题讨论】:

请格式化您的问题。不可读 在每行调用一次的标量函数中的 While 循环并不好。我会开始尝试删除它。 乍一看我会说你可以用递归 CTE 替换标量函数。 如果这是您想要的,请您将下面的答案标记为您问题的答案。 【参考方案1】:

您可以在视图中或树cte之前的CTE中实现该功能,如下所示:-

  ;with prev as (
          select  *,1 [depth],cast(isnull([sequence],'') as varchar(max)) [Tree_full_index] From vwAssesment where parentid is null
          union all
          select v.*,prev.depth+1 [depth],+[Tree_full_index]+'.0'+isnull(v.[sequence],'') from prev
           inner join vwAssesment v on v.parentid=prev.structureid
      ),Tree as (.......

我测试了 prev cte,它将 Tree_full_index 作为 vwAssesment 的所有列的一部分返回,因此将查询更改为使用 prev 而不是 vwAssesment,或者更新 vwAssesment 或创建一个新视图以拥有 Tree_full_index 并使用它

对于以下示例数据:-

Declare @vwAssesment Table(
    structureid int,
    parentid int,
    [sequence] varchar(5)
)
insert into @vwAssesment values(1,null,'1')
insert into @vwAssesment values(2,null,'2')
insert into @vwAssesment values(3,null,'3')
insert into @vwAssesment values(4,1, '1')
insert into @vwAssesment values(5,1, '2')
insert into @vwAssesment values(6,1, '3')
insert into @vwAssesment values(7,2, '2')
insert into @vwAssesment values(8,2, '3')
insert into @vwAssesment values(9,8, '2')
insert into @vwAssesment values(10,8,'3')

结果是:-

structureid parentid    sequence    depth   Tree_full_index
    1           NULL    1           1           1
    2           NULL    2           1           2
    3           NULL    3           1           3
    4           1       1           2           1.01
    5           1       2           2           1.02
    6           1       3           2           1.03
    7           2       2           2           2.02
    8           2       3           2           2.03
    9           8       2           3           2.03.02
    10          8       3           3           2.03.03

【讨论】:

太好了,如果这是您正在寻找的答案,请您将其标记为答案。

以上是关于在 CTE 中实现标量函数的主要内容,如果未能解决你的问题,请参考以下文章

PHP中实现函数重载

用条件在keras中实现自定义丢失函数

我们如何在sql CTE中实现动态查询?

如何在 MySQL 5 .7 中实现 CTE 功能?

SQL Server临时表表标量和CTE

Sql Server 中的标量最大值