Pregunta

Calculation of grp_set is duplicated 4 times in query plan of this query (distinct sort takes 23% each time, so it takes 23 * 4 = 92% of all resources):

with
     grp_set as (select distinct old_num,old_tbl,old_db,old_val_num from err_calc)
    ,grp as (select id = row_number() over (order by old_num),* from grp_set)

    ,leaf as (select grp.id ,c.* ,sort = convert(varchar(max),old_col) + " - " + severity + " - " + err
        from grp
        join err_calc c on
                            c.old_num   = grp.old_num
                        and c.old_tbl       = grp.old_tbl
                        and c.old_db        = grp.old_db
                        and c.old_val_num   = grp.old_val_num
    )

    select old_num,old_tbl,old_db,old_val_num,conc.*
        from (select sep=",") sep
        cross join grp
        cross apply (select
             old_col    = stuff((select sep + old_col   from leaf where leaf.id = grp.id order by leaf.sort FOR XML PATH("")),1,len(sep),"")
            ,old_val    = stuff((select sep + old_val   from leaf where leaf.id = grp.id order by leaf.sort FOR XML PATH("")),1,len(sep),"")
            ,severity   = stuff((select sep + severity  from leaf where leaf.id = grp.id order by leaf.sort FOR XML PATH("")),1,len(sep),"")
            ,err        = stuff((select sep + err       from leaf where leaf.id = grp.id order by leaf.sort FOR XML PATH("")),1,len(sep),"")
        ) conc

Table err_calc contains about 350K records and it has only one index by old_db,old_tbl,new_tbl,severity,err,old_col,new_col,old_val_num,old_val,old_num,new_num.

The purpose of this query is to concatenate 4 string fields per group due to lack of concatenation aggregate in SQL.

Equivalent and desired query if concatenation aggregate existed or was implemented with CLR and if order by could be applied to source of aggregation and if all grouping fields could be referenced by grouping.* would be:

select grouping.*
    ,severity   =conc(sep+severity)
    ,err        =conc(sep+err)
    ,old_col    =conc(sep+old_col)
    ,old_val    =conc(sep+old_val)
    from err_calc
    cross join (select sep=',') sep
    group by old_num,old_tbl,old_db,old_val_num
    order by old_col,severity,err
¿Fue útil?

Solución

Because it is used like a subquery, and used multiple times. cf. Calling CTE multiple times in same query

You should rewrite your query with a JOIN with your CTE instead of a CROSS APPLY, and put the logic of string concatenation in the SELECT part of your query, then the CTE will be called once.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top