【问题标题】:Optimizing SQL Server Query with #temp Table and group by Condition使用 #temp 表和按条件分组优化 SQL Server 查询
【发布时间】:2016-10-05 19:45:12
【问题描述】:

我有以下查询,它按预期工作,但需要很长时间才能执行。

为了获得结果,我已经获取了临时表中的记录,然后应用 groupby 来获得最终结果

SELECT * 
INTO #temp From (

  select A.*,B.* 
  from (
    select e.Id,e.code,e.Fname,
      (select ComboValue from dbo.comvals where Id = c.BUDHOL) as [BUDHOL],
      (select ComboValue from dbo.comvals where Id = c.COMPANY) as [COMPANY],
      (select ComboValue from dbo.comvals where Id = c.BENEFICIARY) as [BENEFICIARY],
      (select ComboValue from dbo.comvals where Id = c.SPARE2) as [SPARE2],
      (select ComboValue from dbo.comvals where Id = c.SPARE1) as [SPARE1],
      (select ComboValue from dbo.comvals where Id = c.EXPORG) as [EXPORG],
      (select ComboValue from dbo.comvals where Id = c.EXPTYPE) as [EXPTYPE],
      (select ComboValue from dbo.comvals where Id = c.OBJECTIVE) as [OBJECTIVE],
      (select ComboValue from dbo.comvals where Id = c.TASKNO) as [TASKNO],
      (select ComboValue from dbo.comvals where Id = c.PROJECTNO) as [PROJECTNO]
    from dbo.EmployeeDetail e  
    left join (
      select * 
      from (
        select CustomeFieldName,FieldValue,CompanyId,EmployeeId   
        from  dbo.CustomeFieldDetail   
        where CustomeFieldName in ('BENEFICIARY','BUDHOL','COMPANY', 'EXPORG','EXPTYPE','OBJECTIVE','PROJECTNO','SPARE2','SPARE1','TASKNO','COMPANY') and CompanyId = 1 
      )as src  
      pivot (max(FieldValue) for CustomeFieldName in ([BENEFICIARY],[BUDHOL],[EXPORG],[EXPTYPE],[OBJECTIVE],[PROJECTNO],[SPARE2],[SPARE1],[TASKNO],[COMPANY])
            ) as src2
    ) c on e.Id = c.EmployeeId   and e.CompanyId = c.CompanyId and e.DateOfJoining <= convert(datetime,'30/03/2016',103) and e.CompanyId = 1       
    where e.Companyid=1 --order by e.Code
  ) A
  Full Outer join (
    select
      T.EmployeeId,
      X.[FieldName],
      X.[Value]
    from dbo.EmpTransaction T
    cross apply (
      SELECT         
        T.c.value('(@Name)[1]', 'Varchar(max)') AS [FieldName],
        convert(float,T.c.value('(@Value)[1]', 'Varchar(max)')) AS [Value]
      FROM TransactionFieldDetails.nodes('//PayDetails/Column') T(c)
      where CompanyId = 1 and  ProcessDate = convert(datetime,'01/03/2016',103) and CategoryId in (1) 
            and T.c.value('(@Name)[1]', 'Varchar(max)') in('FB')
    ) X
  ) B
  ON A.id= B.EmployeeId
) As x

临时表上的最终 GroupBy 条件

SELECT B.BENEFICIARY,
       B.BUDHOL,
       B.COMPANY,
       B.FIELDNAME,
       B.OBJECTIVE,
       B.SPARE1,
       B.SPARE2,
       B.PROJECTNO,
       B.TASKNO,
       B.EXPORG,
       B.EXPTYPE,
       SUM(B.value)
FROM (
    SELECT DISTINCT A.BENEFICIARY,
                    A.BUDHOL,
                    A.COMPANY,
                    A.FIELDNAME,
                    A.OBJECTIVE,
                    A.value,
                    A.SPARE2,
                    A.SPARE1,
                    A.PROJECTNO,
                    A.TASKNO,
                    A.EXPORG,
                    A.EXPTYPE
    FROM (
        SELECT t.BENEFICIARY,
               t.BUDHOL,
               t.COMPANY,
               t.FIELDNAME,
               t.OBJECTIVE,
               t.SPARE1,
               t.SPARE2,
               t.PROJECTNO,
               t.TASKNO,
               t.EXPORG,
               t.EXPTYPE,
               t.value value
        FROM #temp T, #temp TT
    ) A
    LEFT JOIN #temp T1 ON A.BENEFICIARY = t1.BENEFICIARY
        AND A.BUDHOL = t1.BUDHOL
        AND A.COMPANY = t1.COMPANY
        AND A.OBJECTIVE = t1.OBJECTIVE
        AND A.SPARE1 = t1.SPARE1
        AND A.SPARE2 = t1.SPARE2
        AND A.PROJECTNO = t1.PROJECTNO
        AND A.TASKNO = t1.TASKNO
        AND A.EXPORG = t1.EXPORG
        AND A.EXPTYPE = t1.EXPTYPE
) B
GROUP BY B.BENEFICIARY,
         B.BUDHOL,
         B.COMPANY,
         B.OBJECTIVE,
         B.FIELDNAME,
         B.SPARE1,
         B.SPARE2,
         B.PROJECTNO,
         B.TASKNO,
         B.EXPORG,
         B.EXPTYPE

Above Query 工作正常且符合预期。 需要知道上面的查询是否可以优化,这样我就可以花更少的时间来执行目前它需要超过 2 分钟来执行,我们也可以结合两个查询,即我不想使用 #temp

【问题讨论】:

  • 请提供你的执行计划(sqlplan格式)
  • 为什么要做这个交叉连接? : 从#temp T,#temp TT
  • @vercelli 交叉连接以获取所有可能的列组合和值的总和
  • @Devart 执行计划有点无法正确复制。我应该为您提供 xml 格式而不是可视化
  • @Nilesh,您将所有行乘以所有其他行。 10 行给你每行 10 次。不是“列值的组合”。您已经拥有的所有此类“组合” - 这些是您表中的行。您不会通过该交叉连接获得任何 new 行。接下来left join 完全没有意义。您刚刚从该表中选择 - 加入后会出现哪些“惊喜”?

标签: sql sql-server sql-server-2008 group-by temp-tables


【解决方案1】:

合并为 1 个查询

WITH temp AS (

select A.*,B.* from 
(select e.Id,e.code,e.Fname,
(select ComboValue from dbo.comvals where Id = c.BUDHOL) as [BUDHOL],
(select ComboValue from dbo.comvals where Id = c.COMPANY) as [COMPANY],
(select ComboValue from dbo.comvals where Id = c.BENEFICIARY) as [BENEFICIARY],
(select ComboValue from dbo.comvals where Id = c.SPARE2) as [SPARE2],
(select ComboValue from dbo.comvals where Id = c.SPARE1) as [SPARE1],
(select ComboValue from dbo.comvals where Id = c.EXPORG) as [EXPORG],
(select ComboValue from dbo.comvals where Id = c.EXPTYPE) as [EXPTYPE],
(select ComboValue from dbo.comvals where Id = c.OBJECTIVE) as [OBJECTIVE],
(select ComboValue from dbo.comvals where Id = c.TASKNO) as [TASKNO],
(select ComboValue from dbo.comvals where Id = c.PROJECTNO) as [PROJECTNO]
from dbo.EmployeeDetail e  
left join   (select * from   (select CustomeFieldName,FieldValue,CompanyId,EmployeeId   from  dbo.CustomeFieldDetail   where CustomeFieldName in ('BENEFICIARY','BUDHOL','COMPANY', 'EXPORG','EXPTYPE','OBJECTIVE','PROJECTNO','SPARE2','SPARE1','TASKNO','COMPANY') and CompanyId = 1 )as src  pivot (max(FieldValue) for CustomeFieldName in ([BENEFICIARY],[BUDHOL],[EXPORG],[EXPTYPE],[OBJECTIVE],[PROJECTNO],[SPARE2],[SPARE1],[TASKNO],[COMPANY])) as src2) c on e.Id = c.EmployeeId   and e.CompanyId = c.CompanyId and e.DateOfJoining <= convert(datetime,'30/03/2016',103) and e.CompanyId = 1       where e.Companyid=1 --order by e.Code
)A
Full Outer join 
(select
    T.EmployeeId,
    X.[FieldName],
    X.[Value]
from dbo.EmpTransaction T
cross apply (
SELECT         
T.c.value('(@Name)[1]', 'Varchar(max)') AS [FieldName],
convert(float,T.c.value('(@Value)[1]', 'Varchar(max)')) AS [Value]
FROM TransactionFieldDetails.nodes('//PayDetails/Column') T(c)
where CompanyId = 1 and  ProcessDate = convert(datetime,'01/03/2016',103) and CategoryId in (1) 
and T.c.value('(@Name)[1]', 'Varchar(max)') in('FB')
) X )B
ON A.id= B.EmployeeId

 )
 SELECT B.BENEFICIARY,
       B.BUDHOL,
       B.COMPANY,
       B.FIELDNAME,
       B.OBJECTIVE,
       B.SPARE1,
       B.SPARE2,
       B.PROJECTNO,
       B.TASKNO,
       B.EXPORG,
       B.EXPTYPE,
       SUM(B.value)
FROM (
    SELECT DISTINCT A.BENEFICIARY,
                    A.BUDHOL,
                    A.COMPANY,
                    A.FIELDNAME,
                    A.OBJECTIVE,
                    A.value,
                    A.SPARE2,
                    A.SPARE1,
                    A.PROJECTNO,
                    A.TASKNO,
                    A.EXPORG,
                    A.EXPTYPE
    FROM (
        SELECT t.BENEFICIARY,
               t.BUDHOL,
               t.COMPANY,
               t.FIELDNAME,
               t.OBJECTIVE,
               t.SPARE1,
               t.SPARE2,
               t.PROJECTNO,
               t.TASKNO,
               t.EXPORG,
               t.EXPTYPE,
               t.value value
        FROM temp T, temp TT
    ) A
    LEFT JOIN #temp T1 ON A.BENEFICIARY = t1.BENEFICIARY
        AND A.BUDHOL = t1.BUDHOL
        AND A.COMPANY = t1.COMPANY
        AND A.OBJECTIVE = t1.OBJECTIVE
        AND A.SPARE1 = t1.SPARE1
        AND A.SPARE2 = t1.SPARE2
        AND A.PROJECTNO = t1.PROJECTNO
        AND A.TASKNO = t1.TASKNO
        AND A.EXPORG = t1.EXPORG
        AND A.EXPTYPE = t1.EXPTYPE
) B
GROUP BY B.BENEFICIARY,
         B.BUDHOL,
         B.COMPANY,
         B.OBJECTIVE,
         B.FIELDNAME,
         B.SPARE1,
         B.SPARE2,
         B.PROJECTNO,
         B.TASKNO,
         B.EXPORG,
         B.EXPTYPE

【讨论】:

    【解决方案2】:
    IF OBJECT_ID('tempdb.dbo.#temp') IS NOT NULL
        DROP TABLE #temp
    
    SELECT A.*, B.*
    INTO #temp
    FROM (
        SELECT
            e.Id,
            e.code,
            e.Fname,
            c.[BUDHOL],
            c.[COMPANY],
            c.[BENEFICIARY],
            c.[SPARE2],
            c.[SPARE1],
            c.[EXPORG],
            c.[EXPTYPE],
            c.[OBJECTIVE],
            c.[TASKNO],
            c.[PROJECTNO]
        FROM dbo.EmployeeDetail e  
        LEFT JOIN (
            SELECT *
            FROM (
                SELECT
                      d.CustomeFieldName
                    , c.ComboValue
                    , d.EmployeeId
                FROM dbo.CustomeFieldDetail d
                LEFT JOIN dbo.comvals c ON c.Id = d.FieldValue
                WHERE d.CustomeFieldName IN (
                        'BENEFICIARY', 'BUDHOL', 'COMPANY',
                        'EXPORG', 'EXPTYPE', 'OBJECTIVE',
                        'PROJECTNO', 'SPARE2', 'SPARE1',
                        'TASKNO', 'COMPANY'
                    )
                    AND d.CompanyId = 1
            ) src 
            PIVOT (
                MAX(ComboValue)
                FOR CustomeFieldName IN (
                    [BENEFICIARY],[BUDHOL],[EXPORG],
                    [EXPTYPE],[OBJECTIVE],[PROJECTNO],
                    [SPARE2],[SPARE1],
                    [TASKNO],[COMPANY]
               )
            ) src2
        ) c ON e.Id = c.EmployeeId
            AND e.DateOfJoining <= '20160330'
        WHERE e.Companyid = 1
    ) A
    FULL JOIN (
        SELECT t.EmployeeId,
               x.[FieldName],
               x.[Value]
        FROM dbo.EmpTransaction t
        CROSS APPLY (
            SELECT t.c.value('(@Name)[1]', 'VARCHAR(1000)') AS [FieldName],
                   t.c.value('(@Value)[1]', 'FLOAT') AS [Value]
            FROM TransactionFieldDetails.nodes('//PayDetails/Column') t(c)
        ) x
        WHERE [FieldName] = 'FB'
            AND CompanyId = 1
            AND ProcessDate = '20160301'
            AND CategoryId = 1
    ) B ON A.id = B.EmployeeId
    
    SELECT B.BENEFICIARY,
           B.BUDHOL,
           B.COMPANY,
           B.FIELDNAME,
           B.OBJECTIVE,
           B.SPARE1,
           B.SPARE2,
           B.PROJECTNO,
           B.TASKNO,
           B.EXPORG,
           B.EXPTYPE,
           SUM(B.value)
    FROM (
        SELECT DISTINCT A.BENEFICIARY,
                        A.BUDHOL,
                        A.COMPANY,
                        A.FIELDNAME,
                        A.OBJECTIVE,
                        A.value,
                        A.SPARE2,
                        A.SPARE1,
                        A.PROJECTNO,
                        A.TASKNO,
                        A.EXPORG,
                        A.EXPTYPE
        FROM #temp A
        LEFT JOIN #temp T1 ON A.BENEFICIARY = t1.BENEFICIARY
            AND A.BUDHOL = t1.BUDHOL
            AND A.COMPANY = t1.COMPANY
            AND A.OBJECTIVE = t1.OBJECTIVE
            AND A.SPARE1 = t1.SPARE1
            AND A.SPARE2 = t1.SPARE2
            AND A.PROJECTNO = t1.PROJECTNO
            AND A.TASKNO = t1.TASKNO
            AND A.EXPORG = t1.EXPORG
            AND A.EXPTYPE = t1.EXPTYPE
    ) B
    GROUP BY B.BENEFICIARY,
             B.BUDHOL,
             B.COMPANY,
             B.OBJECTIVE,
             B.FIELDNAME,
             B.SPARE1,
             B.SPARE2,
             B.PROJECTNO,
             B.TASKNO,
             B.EXPORG,
             B.EXPTYPE
    

    【讨论】:

      猜你喜欢
      • 2015-10-17
      • 1970-01-01
      • 1970-01-01
      • 2017-07-22
      • 2013-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-04
      相关资源
      最近更新 更多