使用嵌套的内部查询和案例语句优化查询

时间:2019-12-05 06:37:34

标签: sql-server query-optimization sql-server-2017

我下面有某人写的查询(数据库是Microsoft SQL Server 2017)。我无权访问数据库来创建索引等。因此,我唯一能做的就是尽可能有效地优化下面的查询。

我的查询是

我可以在内部查询中使用Case和WHEN吗?目前,我还在尝试使用内部联接删除嵌套查询。

对于以下查询,我们将不胜感激。我不是要给出最终的优化查询,而是要提出以下查询的具体建议。

WITH   ChildPremiumCTE (COVER_PREMIUM_SET_ID,POLICY_ID, ADDRESS_ID, STATUS_CODE,COVER_PREMIUM_MODEL_ID, SUB_PRODUCT_REF
, COVER_PREMIUM_MODEL_REF, DESCRIPTION, PREMIUM_LEVEL_CODE
, PREMIUM_PAYABLE, PREMIUM_DUE, COMMISSION_GST, COMMISSION, COMMISSION_TOTAL,TERRORISM_GST
, TERRORISM_RI, STAMP_DUTY, GST, FSL
, MODIFIED_PREMIUM,  TECHNICAL_PREMIUM, BASE_PREMIUM
, PREMIUM_PAYABLE_TERM, PREMIUM_DUE_TERM, COMMISSION_GST_TERM
, COMMISSION_TERM, COMMISSION_TOTAL_TERM, TERRORISM_GST_TERM
, TERRORISM_RI_TERM, STAMP_DUTY_TERM,  GST_TERM, FSL_TERM
, MODIFIED_PREMIUM_TERM,  TECHNICAL_PREMIUM_TERM,  BASE_PREMIUM_TERM
, PREMIUM_PAYABLE_ANNUALISED, PREMIUM_DUE_ANNUALISED, COMMISSION_GST_ANNUALISED
, COMMISSION_ANNUALISED, COMMISSION_TOTAL_ANNUALISED, TERRORISM_GST_ANNUALISED
, TERRORISM_RI_ANNUALISED,  STAMP_DUTY_ANNUALISED, GST_ANNUALISED
, FSL_ANNUALISED,  MODIFIED_PREMIUM_ANNUALISED,  TECHNICAL_PREMIUM_ANNUALISED
, BASE_PREMIUM_ANNUALISED)
AS (SELECT CPP.COVER_PREMIUM_SET_ID
, CPS.POLICY_ID
, CASE WHEN CPS.PREMIUM_LEVEL_CODE = 'PREMITEM' THEN SS.ADDRESS_ID  ELSE AD.ADDRESS_ID END ADDRESS_ID
, SS.STATUS_CODE
, COALESCE(CPM.COVER_PREMIUM_MODEL_ID, 0) COVER_PREMIUM_MODEL_ID
, CASE WHEN CPS.PREMIUM_LEVEL_CODE = 'POLSUM' THEN 'POLICY_SUMMARY' 
  ELSE CASE WHEN CPS.PREMIUM_LEVEL_CODE = 'SITSUM' THEN 'SITUATION_SUMMARY' ELSE CPS.SUB_PRODUCT_REF END END SUB_PRODUCT_REF
, CPS.COVER_PREMIUM_MODEL_REF
, CPS.DESCRIPTION
, CPS.PREMIUM_LEVEL_CODE
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_PAYABLE' THEN CPP.TRANSACTION_AMOUNT END) PREMIUM_PAYABLE 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_DUE' THEN CPP.TRANSACTION_AMOUNT END) PREMIUM_DUE 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_GST' THEN CPP.TRANSACTION_AMOUNT END) COMMISSION_GST 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION' THEN CPP.TRANSACTION_AMOUNT END) COMMISSION 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_TOTAL' THEN CPP.TRANSACTION_AMOUNT END) COMMISSION_TOTAL 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_GST' THEN CPP.TRANSACTION_AMOUNT END) TERRORISM_GST 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_RI' THEN CPP.TRANSACTION_AMOUNT END) TERRORISM_RI 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'STAMP_DUTY' THEN CPP.TRANSACTION_AMOUNT END) STAMP_DUTY 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'GST' THEN CPP.TRANSACTION_AMOUNT END) GST 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'FSL' THEN CPP.TRANSACTION_AMOUNT END) FSL 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'MODIFIED_PREMIUM' THEN CPP.TRANSACTION_AMOUNT END) MODIFIED_PREMIUM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TECHNICAL_PREMIUM' THEN CPP.TRANSACTION_AMOUNT END) TECHNICAL_PREMIUM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'BASE_PREMIUM' THEN CPP.TRANSACTION_AMOUNT END) BASE_PREMIUM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_PAYABLE' THEN CPP.TERM_AMOUNT END) PREMIUM_PAYABLE_TERM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_DUE' THEN CPP.TERM_AMOUNT END) PREMIUM_DUE_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_GST' THEN CPP.TERM_AMOUNT END) COMMISSION_GST_TERM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION' THEN CPP.TERM_AMOUNT END) COMMISSION_TERM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_TOTAL' THEN CPP.TERM_AMOUNT END) COMMISSION_TOTAL_TERM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_GST' THEN CPP.TERM_AMOUNT END) TERRORISM_GST_TERM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_RI' THEN CPP.TERM_AMOUNT END) TERRORISM_RI_TERM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'STAMP_DUTY' THEN CPP.TERM_AMOUNT END) STAMP_DUTY_TERM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'GST' THEN CPP.TERM_AMOUNT END) GST_TERM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'FSL' THEN CPP.TERM_AMOUNT END) FSL_TERM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'MODIFIED_PREMIUM' THEN CPP.TERM_AMOUNT END) MODIFIED_PREMIUM_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TECHNICAL_PREMIUM' THEN CPP.TERM_AMOUNT END) TECHNICAL_PREMIUM_TERM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'BASE_PREMIUM' THEN CPP.TERM_AMOUNT END) BASE_PREMIUM_TERM 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_PAYABLE' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) PREMIUM_PAYABLE_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_DUE' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) PREMIUM_DUE_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_GST' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) COMMISSION_GST_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) COMMISSION_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_TOTAL' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) COMMISSION_TOTAL_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_GST' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) TERRORISM_GST_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_RI' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) TERRORISM_RI_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'STAMP_DUTY' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) STAMP_DUTY_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'GST' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) GST_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'FSL' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) FSL_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'MODIFIED_PREMIUM' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) MODIFIED_PREMIUM_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TECHNICAL_PREMIUM' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) TECHNICAL_PREMIUM_ANNUALISED 
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'BASE_PREMIUM' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) BASE_PREMIUM_ANNUALISED
FROM COVER_PREMIUM_SET As CPS 
LEFT JOIN SITUATION_SECTION As SS ON CPS.POLICY_ID = SS.POLICY_ID 
     AND CPS.SITUATION_SECTION_REF = SS.SITUATION_SECTION_REF       
LEFT JOIN COVER_PREMIUM_PART As CPP ON CPS.COVER_PREMIUM_SET_ID = CPP.COVER_PREMIUM_SET_ID 
LEFT JOIN ADDRESS As AD ON CPS.POLICY_ID = AD.POLICY_ID 
     AND AD.ADDRESS_REF = CPS.ENTITY_INSTANCE_REF 
     AND CPS.PREMIUM_LEVEL_CODE IN ('SITSUM', 'SUBPRODSUM') 
LEFT JOIN COVER_PREMIUM_MODEL As CPM ON CPS.COVER_PREMIUM_MODEL_REF = CPM.COVER_PREMIUM_MODEL_REF
GROUP BY CPP.COVER_PREMIUM_SET_ID,
CPS.POLICY_ID,
CPS.DESCRIPTION,
CPS.PREMIUM_LEVEL_CODE,
CPS.COVER_PREMIUM_MODEL_REF,
CPS.SUB_PRODUCT_REF,
CPM.COVER_PREMIUM_MODEL_ID,
SS.SITUATION_SECTION_ID,
SS.ADDRESS_ID,
SS.STATUS_CODE,
CPS.ENTITY_INSTANCE_REF,
AD.ADDRESS_ID )

select * from (SELECT
0 AS COVER_PREMIUM_SET_ID
, a1.POLICY_ID
, a1.ADDRESS_ID
, a1.STATUS_CODE
, CPM_CHILD.PARENT_ID AS COVER_PREMIUM_MODEL_ID
, CASE WHEN CPM.PREMIUM_LEVEL_CODE = 'POLSUM' THEN 'POLICY_SUMMARY' 
  ELSE CASE WHEN CPM.PREMIUM_LEVEL_CODE = 'SITSUM' THEN 'SITUATION_SUMMARY' ELSE a1.SUB_PRODUCT_REF END END SUB_PRODUCT_REF
, CPM.COVER_PREMIUM_MODEL_REF
, CPM.NAME AS Description
, CPM.PREMIUM_LEVEL_CODE AS PREMIUM_LEVEL_CODE
, sum(a1.PREMIUM_PAYABLE) PREMIUM_PAYABLE
, sum(a1.PREMIUM_DUE) PREMIUM_DUE
, sum(a1.COMMISSION_GST) COMMISSION_GST
, sum(a1.COMMISSION) COMMISSION
, sum(a1.COMMISSION_TOTAL) COMMISSION_TOTAL,sum(a1.TERRORISM_GST) TERRORISM_GST
, sum(a1.TERRORISM_RI) TERRORISM_RI, sum(a1.STAMP_DUTY) STAMP_DUTY,sum(a1.GST ) GST, sum(a1.FSL ) FSL
, sum(a1.MODIFIED_PREMIUM ) MODIFIED_PREMIUM,  sum(a1.TECHNICAL_PREMIUM ) TECHNICAL_PREMIUM, sum(a1.BASE_PREMIUM ) BASE_PREMIUM
, sum(a1.PREMIUM_PAYABLE_TERM) PREMIUM_PAYABLE_TERM, sum(a1.PREMIUM_DUE_TERM ) PREMIUM_DUE_TERM
, sum(a1.COMMISSION_GST_TERM ) COMMISSION_GST_TERM,  sum(a1.COMMISSION_TERM ) COMMISSION_TERM
, sum(a1.COMMISSION_TOTAL_TERM ) COMMISSION_TOTAL_TERM, sum(a1.TERRORISM_GST_TERM ) TERRORISM_GST_TERM
, sum(a1.TERRORISM_RI_TERM ) TERRORISM_RI_TERM, sum(a1.STAMP_DUTY_TERM ) STAMP_DUTY_TERM
, sum(a1.GST_TERM ) GST_TERM, sum(a1.FSL_TERM ) FSL_TERM, sum(a1.MODIFIED_PREMIUM_TERM ) MODIFIED_PREMIUM_TERM
, sum(a1.TECHNICAL_PREMIUM_TERM ) TECHNICAL_PREMIUM_TERM,  sum(a1.BASE_PREMIUM_TERM ) BASE_PREMIUM_TERM
, sum(a1.PREMIUM_PAYABLE_ANNUALISED) PREMIUM_PAYABLE_ANNUALISED, sum(a1.PREMIUM_DUE_ANNUALISED ) PREMIUM_DUE_ANNUALISED
, sum(a1.COMMISSION_GST_ANNUALISED ) COMMISSION_GST_ANNUALISED,  sum(a1. COMMISSION_ANNUALISED ) COMMISSION_ANNUALISED
, sum(a1. COMMISSION_TOTAL_ANNUALISED ) COMMISSION_TOTAL_ANNUALISED, sum(a1.TERRORISM_GST_ANNUALISED ) TERRORISM_GST_ANNUALISED
, sum(a1.TERRORISM_RI_ANNUALISED ) TERRORISM_RI_ANNUALISED,  sum(a1.STAMP_DUTY_ANNUALISED ) STAMP_DUTY_ANNUALISED
, sum(a1.GST_ANNUALISED ) GST_ANNUALISED, sum(a1.FSL_ANNUALISED ) FSL_ANNUALISED
,  sum(a1.MODIFIED_PREMIUM_ANNUALISED ) MODIFIED_PREMIUM_ANNUALISED
, sum(a1.TECHNICAL_PREMIUM_ANNUALISED ) TECHNICAL_PREMIUM_ANNUALISED
, sum(a1.BASE_PREMIUM_ANNUALISED) BASE_PREMIUM_ANNUALISED

FROM COVER_PREMIUM_MODEL CPM,
COVER_PREMIUM_MODEL CPM_CHILD,
ChildPremiumCTE a1
WHERE
                    CPM.PREMIUM_LEVEL_CODE = 'PREMRLUP' 
                    AND CPM_CHILD.PARENT_ID = CPM.COVER_PREMIUM_MODEL_ID 
                    AND CPM_CHILD.COVER_PREMIUM_MODEL_REF = a1.COVER_PREMIUM_MODEL_REF
            GROUP BY
                a1.POLICY_ID,
                a1.ADDRESS_ID,
                CPM_CHILD.PARENT_ID,
                CPM.NAME,
                CPM.PREMIUM_LEVEL_CODE,
                a1.SUB_PRODUCT_REF,
                CPM.COVER_PREMIUM_MODEL_REF,
                a1.STATUS_CODE 
 UNION ALL
 select * from  ChildPremiumCTE) CoverPremium where CoverPremium.POLICY_ID = 77780029

到目前为止,我已经改进了,

  • 建立工会以统一所有人
  • 尝试将子查询转换为where子句
  • 内置MAX,SUM之类的函数来喜欢字符串文字

1 个答案:

答案 0 :(得分:2)

第一个建议与@LukStorms相同,也总是使用表的别名并在列中添加前缀,以便于理解和调试。

  

我可以在内部查询中使用Case和WHEN吗?

一切都有成本。在这种情况下,成本似乎可以忽略不计。

  

对于以下查询,我们将不胜感激。我不是   要求给出最终的优化查询,但要求具体建议   到下面的查询。

    在“全部”列上
  1. GROUP BY总是一个坏主意。首先使用CTE或#Temp表 仅使用“ require”表和“ Group on on Key”列来编写Group By查询。

假设您还需要其他一些列,该列也不属于聚合或分组依据,那么请不要在此处尝试使用该列。 在主查询中联接同一表,以获取不属于聚合的那些列。

然后在Main查询中再次将该CTE或temp表与其他表联接。

这是设计查询的方式。

  

PREMIUM_MODEL_PART_REF and TRANSACTION_AMOUNT belong to which table ?

COVER_PREMIUM_MODEL在查询中使用了3次。将COVER_PREMIUM_MODEL的需求数据放在#temp table上。这三个联接必须有一些共同的结果。

节选

select * from (Select * blah blah
UNION ALL
 select * from     ChildPremiumCTE) a2 where a2.POLICY_ID = 77780029

为什么最后使用where POLICY_ID = 77780029? 这样,首先将在内部查询中处理大量行,然后最终减少到POLICY_ID = 77780029

所以为什么不首先在内部查询中使用POLICY_ID = 77780029

  

内置MAX,SUM之类的函数来喜欢字符串文字

这取决于UDF的类型以及您所写的内容。 简而言之,UDF在大多数情况下都是糟糕的表现。

似乎不是MAX, SUM需要UDF