【问题标题】:Full Outer Join not returning unmatched join field values SQL SERVER 2005完全外连接不返回不匹配的连接字段值 SQL SERVER 2005
【发布时间】:2011-11-22 17:39:35
【问题描述】:

我使用下面的代码来计算给定月份(在本例中为 9 月)按承保范围(汽车)赚取的保费。代码所做的是减去截至 9 月 30 日的所有时间赚取的总保费减去截至 8 月 31 日的所有时间赚取的总保费,以返回仅在 9 月份赚取的保费。

结果如下所示:

eprem        coveragecode  
0.0211       AD  
277970.8291  BI  
245700.6741  COLL  
86997.5694   COMP  
85.0083      CustomParts  
848.7873     Death  
0.00         ECL  
0.00         GPIP  
692.3802     Income  
2410.5513    MED  
267670.1099  PD  
387628.504   PIP  
26.8767      PU  
11736.2762   Rental  
4304.3367    Towing   
4211.2574    UIMBI  
19804.8964   UMBI  
15145.3211   UMPD  

当我将所有保险的保费加起来时,我得到 1325233.399,这是 9 月份赚取的正确保费金额。

现在我要做的是在结果中添加邮政编码字段。如果我在代码中没有指定邮政编码列的情况下运行下面的代码,那么我得到的上述结果是正确的,但是当我添加邮政编码列时,我会返回数千行,这是预期的,但是当我加起来我得到的总保费时1323608.401 而不是正确的总数 1325233.399。我相信正在发生的事情是在一个月(派生表)中存在某些覆盖范围和邮政编码组合(这是我加入我的 2 个派生表的内容),并在另一个中注明。当我进行右连接时,我得到不同数量的行返回,当我做左连接时,但是当我将所有保费加起来时,它总是等于 1323608.401 而不是 1325233.399 。我认为解决我的问题的方法是使用完整的外部联接,从而返回所有结果(即使是那些不匹配的结果),这样我的总保费将加起来 1325233.399 但无论哪种类型的联接,我仍然只能得到 1323608.401我尝试使用。有谁知道这里可能发生了什么???任何帮助将不胜感激。谢谢!

    SELECT   sept.eprem-aug.eprem as eprem , sept.coveragecode, zipcode 
from

(select 
SUM(EarnedPremium) AS eprem,coveragecode, evaluationdate, zipcode                       
FROM         dbo.StatRateSummary                            
where evaluationdate = '09-30-2011' 
and decpagetypecode != 'x'
GROUP BY evaluationdate ,coveragecode, zipcode

) as sept full outer join 

(select 
SUM(EarnedPremium) AS eprem,coveragecode, evaluationdate, zipcode                       
FROM         dbo.StatRateSummary                            
where evaluationdate = CONVERT(DATETIME, DATEADD(d,-1,DATEADD(mm, DATEDIFF(m,0,'09-30-2011'),0)), 102)  
and decpagetypecode != 'x'
GROUP BY evaluationdate ,coveragecode, zipcode

) as aug on sept.coveragecode = aug.coveragecode and sept.zipcode = aug.zipcode
where sept.coveragecode is not null and sept.coveragecode <> ''
order by coveragecode, sept.evaluationdate

【问题讨论】:

  • EarnedPremium 是什么数据类型?
  • 这是一种“金钱”数据类型

标签: sql sql-server-2005 outer-join


【解决方案1】:

我所要做的就是更改第一行代码以将任何 null 溢价值转换为 0。

SELECT   isnull(sept.eprem,0)-isnull(aug.eprem,0) as eprem , sept.coveragecode, zipcode 
from

(select 
SUM(EarnedPremium) AS eprem,coveragecode, evaluationdate, zipcode                       
FROM         dbo.StatRateSummary                            
where evaluationdate = '09-30-2011' 
and decpagetypecode != 'x'
GROUP BY evaluationdate ,coveragecode, zipcode

) as sept full outer join 

(select 
SUM(EarnedPremium) AS eprem,coveragecode, evaluationdate, zipcode                       
FROM         dbo.StatRateSummary                            
where evaluationdate = CONVERT(DATETIME, DATEADD(d,-1,DATEADD(mm, DATEDIFF(m,0,'09-30-2011'),0)), 102)  
and decpagetypecode != 'x'
GROUP BY evaluationdate ,coveragecode, zipcode

) as aug on sept.coveragecode = aug.coveragecode and sept.zipcode = aug.zipcode
where sept.coveragecode is not null and sept.coveragecode <> ''
order by coveragecode, sept.evaluationdate

【讨论】:

    【解决方案2】:

    您的 FULL OUTER JOIN 条件应如下所示:

    SELECT   sept.eprem-aug.eprem as eprem , sept.coveragecode, zipcode 
    from
    
    (select 
    SUM(EarnedPremium) AS eprem,coveragecode, evaluationdate, zipcode                       
    FROM         dbo.StatRateSummary                            
    where evaluationdate = '09-30-2011' 
    and decpagetypecode != 'x'
    -- Migrated WHERE Condition
    AND COALESCE(eprem.coveragecode, '') > ''
    GROUP BY evaluationdate ,coveragecode, zipcode
    
    ) as sept FULL OUTER join 
    
    (select 
    SUM(EarnedPremium) AS eprem,coveragecode, evaluationdate, zipcode                       
    FROM         dbo.StatRateSummary                            
    where evaluationdate = CONVERT(DATETIME, DATEADD(d,-1,DATEADD(mm, DATEDIFF(m,0,'09-30-2011'),0)), 102)  
    and decpagetypecode != 'x'
    GROUP BY evaluationdate ,coveragecode, zipcode
    
    ) as aug on sept.coveragecode = aug.coveragecode and sept.zipcode = aug.zipcode
    /*
    || See SEPT derived table for elimination of NULL and '' coverage codes
    || where sept.coveragecode is not null and sept.coveragecode <> ''
    */
    order by coveragecode, sept.evaluationdate
    

    需要考虑的一点是,当您使用 OUTER JOIN 时,WHERE 条件可能会导致优化器将 JOIN 重写为 INNER JOIN .

    希望这会有所帮助。

    【讨论】:

    • 您好 Rob,感谢您的回复。我刚刚尝试了代码,起初我收到一条错误消息,说 Zipcode 是一个模棱两可的列名,所以我选择使用 sept.zipcode 然后我尝试了 aug.zipcode 然后我在 select 语句中尝试了这两个结果仍然给我 1323608.401 的总保费,而不是 1325233.399 金额,这是 9 月正确赚取的保费金额。我正在运行以获取 1325233.399 号码的代码与我原来的问题中的代码相同,但在代码中的任何地方都没有对 zipcode 列的任何引用。
    • 这太奇怪了,无论我使用什么类型的连接,我都会得到 1323608.401 总数...
    • 意识到我在 ON 子句中留下了 ZIPCODE。如果您删除它并重新提交查询会怎样?
    • 我从 ON 子句中删除了 ZIPCODE,查询返回了数百万条记录,保费总额为 -61210318.62。在 ON 子句中使用带有 ZIPCODE 的原始代码,返回的总保费 1323608.401 仅减少约 2,000 美元。
    • 我刚刚发现出了什么问题。在 select 语句中我的代码的第一行中,我减去了不同的 eprem 值,但是由于我正在执行完整的外部联接,因此有时 sept.eprem 或 aug.eprem 为空,因此不是正常计算,而是假设 $25 - $10= $15 我会得到类似 $25 - NULL = NULL 而不是 $25 - NULL = $25。我现在需要做的就是编写一个 IF 或 CASE 语句或使用其中一个替换函数,以便如果 aug.eprem 或 sept.eprem 为 NULL,则使其等于 $0,以便可以正确执行 eprem 计算。跨度>
    猜你喜欢
    • 1970-01-01
    • 2018-11-26
    • 2019-10-25
    • 2019-03-08
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 2012-01-06
    相关资源
    最近更新 更多