クエリの最初の部分は、Policy
のPremiums
,Effective
およびExpiration
の日付を取得します。 2番目の部分はCalendar
を作成し、3番目の部分(最終SELECT
文)はMonth
とYear
の順に分解されます。 すべて正常に動作し、結果を表示するのにわずか3秒かかります。 しかし、私はフィルタリングする必要がありますPolicyNumber
は、基本的に私はPolicyNumber
を取り除く必要があるのは@ClassCode
を持っていないです。だから私はWHERE
句置かれ、クエリの最初の部分で、そのために:私はこの文を持っている@Prdpユーザにサブクエリを使用するときのクエリパフォーマンスを向上させる方法
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を:Caseステートメントは、他のNULLがなるリストに存在するClassCodeのための1を生成します生成される。カウント集計は、各PolicyNumberについて1をカウントします。 = 0を設定することで、PolicyNumberに指定されたリストにClassCodeが存在しないことを確認できます。
このクエリが永遠に回転した後、@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両方のテーブルのPolicyNumber
にnon-clustered
というインデックスを作成しました。しかし、まだ何も。 SQL Engineが3秒かかる最初の部分(PolicyNumberフィルタリング)を処理し、次にもう3秒かかる2番目の部分(それらのPolicyNumberの計算)を実行すると、それは素晴らしいと思われます。 しかし、私はDBAを初めて熟知しているので、その可能性についてもわかりません。 アドバイスはありますか? おかげ
実行計画::
Codereview.stackexchange.comは 'tblClassCodesPlazaCommercial'が' NULL ClassCode'を持っているdoesntのこの – scsimon