为什么SP与具有相同过滤器的SELECT语句的结果略有不同

时间:2016-12-02 20:55:48

标签: sql-server tsql stored-procedures exists

无法理解为什么存储过程的结果与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

这是SP的结果: enter image description here

这是SELECT查询的结果:

enter image description here

这就是policy_data结果的样子

enter image description here

0 个答案:

没有答案