无法理解为什么存储过程的结果与SELECT
语句略有不同。在SP中,我使用#TempTable
过滤我的数据,然后使用EXISTS语句。
在我的SELECT
中查询WHERE
子句中的相同值。
我尝试逐个参数,只有SICCode
影响结果。
这是我的SP:
ALTER PROCEDURE [dbo].[EarningPlazaCommercial]
@State varchar(50),
@StartDate datetime,
@EndDate datetime,
@AsOfDate datetime,
@SICCode nvarchar(max),
@Coverage varchar(100)
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #PolicyNumbers (PolicyNumber varchar(50))
INSERT INTO #PolicyNumbers SELECT PolicyNumber
FROM PlazaInsuranceWPDataSet
WHERE SICCode IN (SELECT * FROM [dbo].[StringOfStringsToTable](@SICCode,','))
AND State IN (SELECT * FROM [dbo].[StringOfStringsToTable](@State,','))
AND Coverage IN (SELECT * FROM [dbo].[StringOfStringsToTable](@Coverage,','))
CREATE CLUSTERED INDEX IDX_C_PolicyNumbers_PolicyNumber ON #PolicyNumbers(PolicyNumber)
; WITH Earned_to_date AS (
SELECT CAST(@AsOfDate AS DATE) AS Earned_to_date
), policy_data AS (
SELECT
PolicyNumber,
--Coverage
Cast(PolicyEffectiveDate AS DATE) AS PolicyEffectiveDate
, Cast(PolicyExpirationDate AS DATE) AS PolicyExpirationDate
, WrittenPremium
--, --State
FROM PlazaInsuranceWPDataSet piwp
WHERE EXISTS (SELECT PolicyNumber FROM #PolicyNumbers pn WHERE pn.PolicyNumber = piwp.PolicyNumber)
)
, 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 @StartDate AND @EndDate
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
DROP TABLE #PolicyNumbers
END 然后我执行它:
EXEC [dbo].[EarningPlazaCommercial] @State='CA,NV,AZ',
@StartDate = '01-01-2015',
@EndDate = '10-31-2016',
@AsOfDate = '11-30-2016',
@SICCode = '0161,0173,0179,0181,0191,0722,0752,0761,0782,1440,1441,1442,1521,1522,161,1611,1629,1711,172,1731,1742',
@Coverage = 'Uninsured,Medical,Physical Damage,Premises,Terrorism,Underinsured,Liability'
这是我的SELECT
查询:
; WITH Earned_to_date AS (
SELECT Cast('11-30-2016' AS DATE) AS Earned_to_date
), policy_data AS (
SELECT
PolicyNumber
, Cast(PolicyEffectiveDate AS DATE) AS PolicyEffectiveDate
, Cast(PolicyExpirationDate AS DATE) AS PolicyExpirationDate
, WrittenPremium
FROM PlazaInsuranceWPDataSet
WHERE State IN ('CA','AZ','NV')
AND SICCode IN ('0161','0173','0179','0181','0191','0722','0752','0761','0782','1440','1441','1442','1521','1522','161','1611','1629','1711','172','1731','1742')
AND Coverage IN ('Uninsured','Medical','Physical Damage','Premises','Terrorism','Underinsured','Liability')
)
, 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 '10-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
我在这里缺少什么?
这是拆分函数StringOfStringsToTable
ALTER FUNCTION [dbo].[StringOfStringsToTable]
(
@Strings varchar(8000),
@Separator char(1)
)
RETURNS @StringTable table (String varchar(500))
AS
BEGIN
DECLARE @String varchar(500), @Pos int
SET @Strings = LTRIM(RTRIM(@Strings))+ @Separator
SET @Pos = CHARINDEX(@Separator, @Strings, 1)
WHILE @Pos > 0
BEGIN
SET @String = LTRIM(RTRIM(LEFT(@Strings, @Pos - 1)))
IF @String <> '' INSERT INTO @StringTable VALUES (@String)
SET @Strings = RIGHT(@Strings, LEN(@Strings) - @Pos)
SET @Pos = CHARINDEX(@Separator, @Strings, 1)
END
RETURN
END
这是SELECT查询的结果:
这就是policy_data
结果的样子