查询的第一部分获取Policy
的Premiums
,Effective
和Expiration
日期。 第二部分创建Calendar
,第三部分(最终SELECT
声明)返回的收益细分为Month
和Year
一切正常,只需3秒即可显示结果。 但后来我需要过滤什么PolicyNumber
的工作,基本上我需要摆脱PolicyNumber
的没有@ClassCode
。因此,对于在查询的第一部分,我把WHERE
条款:如何提高使用子查询时的查询性能
WHERE State IN ('CA','NV','AZ')
AND PolicyNumber IN (
SELECT PolicyNumber
FROM tblClassCodesPlazaCommercial
GROUP BY PolicyNumber
HAVING COUNT (CASE WHEN ClassCode NOT IN (@ClassCode)
THEN 1 END)=0
)
Thanksful到@Prdp用户我有这样的说法:Case语句将产生1对存在于列表中其他NULL将是ClassCode产生。现在,每个PolicyNumber的计数聚合将计为1。通过设置= 0,我们可以确保PolicyNumber在给定列表中没有任何ClassCode。
查询永久性后,在SSRS报告中可以有多于的200 ClassCodes
。
有趣的是,这两个语句单独工作正常。但是,当我使用它们在一起(这是摆在cte policy_data
WHERE
条款则执行需要永远。 是没有办法告诉引擎进行查询,这是
; WITH Earned_to_date AS (
SELECT Cast(EOMONTH (GETDATE(), -1) AS DATE) AS Earned_to_date
), policy_data AS (
SELECT
PolicyNumber
, Cast(PolicyEffectiveDate AS DATE) AS PolicyEffectiveDate
, Cast(PolicyExpirationDate AS DATE) AS PolicyExpirationDate
, WrittenPremium
, State
FROM PlazaInsuranceWPDataSet
WHERE State IN ('CA','NV','AZ')
/* -------This statement gives me trouble ----------------------*/
AND PolicyNumber IN (
SELECT PolicyNumber
FROM tblClassCodesPlazaCommercial
GROUP BY PolicyNumber
HAVING COUNT (CASE WHEN ClassCode NOT IN (5151)
THEN 1 END)=0
)
)
,然后计算和突破的第一部分下来收益只有那些已被过滤政策
我的整个代码如下:
; WITH Earned_to_date AS (
SELECT Cast(EOMONTH (GETDATE(), -1) AS DATE) AS Earned_to_date
), policy_data AS (
SELECT
PolicyNumber
, Cast(PolicyEffectiveDate AS DATE) AS PolicyEffectiveDate
, Cast(PolicyExpirationDate AS DATE) AS PolicyExpirationDate
, WrittenPremium
, State
FROM PlazaInsuranceWPDataSet
WHERE State IN ('CA','NV','AZ')
/* -------This statement gives me trouble ----------------------*/
AND PolicyNumber IN (
SELECT PolicyNumber
FROM tblClassCodesPlazaCommercial
GROUP BY PolicyNumber
HAVING COUNT (CASE WHEN ClassCode NOT IN (@ClassCode)
THEN 1 END)=0
)
)
, digits AS (
SELECT digit
FROM (VALUES (0), (1), (2), (3), (4)
, (5), (6), (7), (8), (9)) AS z2 (digit)
), numbers AS (
SELECT 1000 * d4.digit + 100 * d3.digit + 10 * d2.digit + d1.digit AS number
FROM digits AS d1
CROSS JOIN digits AS d2
CROSS JOIN digits AS d3
CROSS JOIN digits AS d4
), calendar AS (
SELECT
DateAdd(month, number, '1753-01-01') AS month_of
, DateAdd(month, number, '1753-02-01') AS month_after
FROM numbers
), policy_dates AS (
SELECT
PolicyNumber
, CASE
WHEN month_of < PolicyEffectiveDate THEN PolicyEffectiveDate
ELSE month_of
END AS StartRiskMonth
, CASE
WHEN PolicyExpirationDate < month_after THEN PolicyExpirationDate
WHEN Earned_to_date.Earned_to_date < month_after THEN Earned_to_date
ELSE month_after
END AS EndRiskMonth
, DateDiff(day, PolicyEffectiveDate, PolicyExpirationDate) AS policy_days
, WrittenPremium
FROM policy_data
JOIN calendar
ON (policy_data.PolicyEffectiveDate < calendar.month_after
AND calendar.month_of < policy_data.PolicyExpirationDate)
CROSS JOIN Earned_to_date
WHERE month_of < Earned_to_date
)
SELECT
Year(StartRiskMonth) as YearStartRisk,
Month(StartRiskMonth) as MonthStartRisk,
c.YearNum,c.MonthNum,
convert(varchar(7), StartRiskMonth, 120) as RiskMonth,
sum(WrittenPremium * DateDiff(day, StartRiskMonth, EndRiskMonth)/policy_days) as EarnedPremium
FROM tblCalendar c
LEFT JOIN policy_dates l ON c.YearNum=Year(l.StartRiskMonth) AND c.MonthNum = Month(l.StartRiskMonth)
AND l.StartRiskMonth BETWEEN '01-01-2015' AND '12-31-2016'
WHERE c.YearNum Not IN (2017)
GROUP BY convert(varchar(7), StartRiskMonth, 120),
Year(StartRiskMonth) , Month(StartRiskMonth),
c.YearNum,c.MonthNum
ORDER BY c.YearNum,c.MonthNum
什么将是提高性能的最佳方式? 10我在两张表上创建了non-clustered
索引PolicyNumber
。但仍然没有。 就像我说的,在我看来,如果SQL引擎会处理需要3秒的第一部分(PolicyNumber筛选),然后执行另外3秒的部分(计算这些PolicyNumber的部分) - 这太棒了。 但我是DBA的新手,所以我不确定它有可能。 有什么建议吗? 感谢
执行计划::
Codereview.stackexchange.com是这个 – scsimon