【问题标题】:Last two joins cause duplicate rows最后两个连接导致重复行
【发布时间】:2014-02-04 17:11:59
【问题描述】:

好的,所以我有一个查询返回的行数比预期的重复数据多。这是我的查询:

SELECT AP.RECEIPTNUMBER
,AP.FOLDERRSN
,ABS(AP.PAYMENTAMOUNT)
,ABS(AP.PAYMENTAMOUNT - AP.AMOUNTAPPLIED)
,TO_CHAR(AP.PAYMENTDATE,'MM/DD/YYYY')
,F.REFERENCEFILE
,F.FOLDERTYPE
,VS.SUBDESC
,P.NAMEFIRST||' '||P.NAMELAST
,P.ORGANIZATIONNAME
,VAF.FEEDESC
,VAF.GLACCOUNTNUMBER

FROM ACCOUNTPAYMENT AP

INNER JOIN FOLDER F ON AP.FOLDERRSN = F.FOLDERRSN
INNER JOIN VALIDSUB VS ON F.SUBCODE = VS.SUBCODE
INNER JOIN FOLDERPEOPLE FP ON FP.FOLDERRSN = F.FOLDERRSN
INNER JOIN PEOPLE P ON FP.PEOPLERSN = P.PEOPLERSN
INNER JOIN ACCOUNTBILLFEE ABF ON F.FOLDERRSN = ABF.FOLDERRSN
INNER JOIN VALIDACCOUNTFEE VAF ON ABF.FEECODE = VAF.FEECODE

WHERE AP.NSFFLAG = 'Y'
AND F.FOLDERTYPE IN ('405B','405O')

在我添加底部的两个内连接之前一切正常。我基本上是想获得所有有 NSF 的付款。当我运行简单查询时:

SELECT *
FROM ACCOUNTPAYMENT
WHERE NSFFLAG = 'Y'

我只有 3 行与 405B 和 405O 文件夹有关。所以我只希望在上面的查询中返回 3 行,但我得到 9 行,其中信息在某些列中重复。我需要基于有效账户费用和账户账单费用表中的费用代码的确切 feedesc 和 gl 帐号。

我无法发布我的输出图片。

注意:当我在没有两个底部连接的情况下运行查询时,我得到了预期的输出。

有人可以帮助我提高查询效率吗?谢谢!

根据要求,以下是我的查询为 vaf.feedesc 和 vaf.glaccountnumber 列返回的结果:

Boiler Operator License Fee                                         2423809
Boiler Certificate of Operation without Manway - Revolving          2423813
Installers (Boiler License)/API Exam                            2423807
Boiler Public Inspection/Certification (State or Insurance)         2423816
Boiler Certificate of Operation with Manway                         2423801
Boiler Certificate of Operation without Manway                  2423801
Boiler Certificate of Operation with Manway - Revolving         2423813
BPV Owner/User Program Fee                                          2423801
Installers (Boiler License)/API Exam Renewal                    2423807

【问题讨论】:

  • 使用DISTINCT 解释here 来获得不同的行。至于为什么结果中有多行,您必须查看最后两个表的所有列的值。您可能缺少另一个过滤条件。
  • “注意:当我在没有两个底部连接的情况下运行查询时,我会得到预期的输出。” 然后不要使用这两个连接。
  • 谢谢,但使用 DISTINCT 并不能帮助我处理多行(如您所述)我应该在最后两个表中所有列的值中查找什么?
  • @DEwok 只需选择最后 2 个表的所有列并检查行的输出以查看值变化的地方。这将让您知道为什么前面表格的每个结果都是 JOINing 以及其他表格的多行。
  • @user2989408 是对的。如果不了解有关ACCOUNTBILLFEEVALIDACCOUNTFEE 表的更多信息(列和行),我们无法完全回答您的问题。但你的问题肯定存在。

标签: sql sql-server join


【解决方案1】:

原因是至少有一个连接ACCOUNTBILLFEE-FOLDERVALIDACCOUNTFEE-ACCOUNTBILLFEE 不是一对一的。它允许一个文件夹拥有多个AccountBillFees,或者一个ValidAccountFee拥有多个AccountBillFees

为了找到此类问题的原因,我通常会这样做:

  • 将查询的SELECT A, B, C 部分更改为SELECT *
  • 将结果减少到导致您遇到问题的行之一(通过添加WHERE ...)。这是没有最后两个连接的单行,以及添加这两个连接后的几行。
  • 从左到右查看结果表。第一列可能会为所有行显示相同的值。一旦您看到列中的值之间存在差异,您就知道您当前正在查看的列的表正在导致您的“多行问题”。
  • 现在创建一个 SELECT * 语句,其中仅包含连接在一起的两个表,这会导致多行具有您在上面使用的相同 WHERE ...
  • 结果应该让您清楚地了解原因。
  • 一旦您知道问题的原因,您就可以想出一个解决方案;)

【讨论】:

    【解决方案2】:

    试试这个,如果它有帮助,那么这些表有额外的不相关的行。如果没有,请查看我在下面的子查询的结果,看看需要哪些额外的过滤器

    SELECT AP.RECEIPTNUMBER
    ,AP.FOLDERRSN
    ,ABS(AP.PAYMENTAMOUNT)
    ,ABS(AP.PAYMENTAMOUNT - AP.AMOUNTAPPLIED)
    ,TO_CHAR(AP.PAYMENTDATE,'MM/DD/YYYY')
    ,F.REFERENCEFILE
    ,F.FOLDERTYPE
    ,VS.SUBDESC
    ,P.NAMEFIRST||' '||P.NAMELAST
    ,P.ORGANIZATIONNAME
    ,VAF.FEEDESC
    ,VAF.GLACCOUNTNUMBER
    
    FROM ACCOUNTPAYMENT AP
    
    INNER JOIN FOLDER F ON AP.FOLDERRSN = F.FOLDERRSN
    INNER JOIN VALIDSUB VS ON F.SUBCODE = VS.SUBCODE
    INNER JOIN FOLDERPEOPLE FP ON FP.FOLDERRSN = F.FOLDERRSN
    INNER JOIN PEOPLE P ON FP.PEOPLERSN = P.PEOPLERSN
    INNER JOIN 
    (
       SELECT DISTINCT ABF.FEECODE, ABF.FOLDERRSN
       FROM ACCOUNTBILLFEE ABF
    ) ABF ON F.FOLDERRSN = ABF.FOLDERRSN
    INNER JOIN 
    (
      SELECT DISTINCT VAF.FEEDESC, VAF.GLACCOUNTNUMBER, VAF.FEECODE
      FROM VALIDACCOUNTFEE VAF
    ) VAF ON ABF.FEECODE = VAF.FEECODE
    WHERE AP.NSFFLAG = 'Y'
    AND F.FOLDERTYPE IN ('405B','405O')
    

    【讨论】:

    • 仍然得到所有 9 行
    • @DEwok - 正如我在回答中所说,看看有什么区别。 FEECODE, FOLDERSN 对于您的 FOLDERSN 值有什么不同,或者 FEEDESC, GLACCOUNTNUMBER, FEECODE 对于您的 FEECODE 值有什么不同。然后返回给客户、PM 或 BA 并阐明要求。
    • @DEwok - 查看您更新的问题,我认为 GLACCOUNTNUMBER 包含在 VALIDACCOUNTFEE 之外的另一个表中。如果是这种情况,则在 GLACCOUNTNUMBER 上而不是在 FEECODE 上进行最终连接。
    【解决方案3】:

    最后两个表的数据在一对多关系的不同记录中是不同的。由于 distinct 没有解决问题,因此您必须接受 9 条记录是正确的返回,因为您要返回不同的字段,或者您必须根据业务规则确定不希望返回的多条记录中的哪一条必须来自贵公司的某个人,而不是我们。

    我认为您并不完全了解 SQl 的工作原理,因为 9 条记录正是根据您在问题中提供的信息我所期望的。以下是一些查询,它们显示了加入一对多关系如何影响输出,以及您可以调整查询以消除重复输出的方式。

    请注意,在某些情况下,由于要返回的列,无法调整查询以消除输出。因此,即使某些列重复,即使您要返回的列之一具有不同的记录,并且您没有适当的业务规则来查看要查看的列,您也无法减少记录集。您需要哪些规则取决于您要查询的数据类型和要求是什么。这不是我们可以在这里回答的问题,只有您的公司知道最小值或最大值是否可以接受,或者您是否需要添加 where 子句,如果需要,将其放在哪个字段上以及使用它排除哪些值。这些是业务规则而不是 SQL。

    create table #temp (myid int , mydescription varchar(30))
    
    insert into #temp(myid, mydescription)
    values (1, 'test') , (2, 'test2')
    
    create table #temp2 (myid int, myotherdescription varchar(30))
    
    insert into #temp2(myid, myotherdescription)
    values (1, 'othertest') , (1, 'othertest2'), (2, 'myothertest') , (1, 'othertest3')
    
    select * 
    from #temp t
    join #temp2 t2 on t.myid = t2.myid
    
    select t2.myid, t.mydescription
    from #temp t
    join #temp2 t2 on t.myid = t2.myid
    
    select distinct t2.myid, t.mydescription
    from #temp t
    join #temp2 t2 on t.myid = t2.myid
    
    select t.myid, t.mydescription, t2.myotherdescription
    from #temp t
    join #temp2 t2 on t.myid = t2.myid
    
    select distinct t.myid, t.mydescription, t2.myotherdescription
    from #temp t
    join #temp2 t2 on t.myid = t2.myid
    
    select t.myid, min(t2.myotherdescription)
    from #temp t
    join #temp2 t2 on t.myid = t2.myid
    group by t.myid
    
    select t.myid, t2.myotherdescription
    from #temp t
    join #temp2 t2 on t.myid = t2.myid
    where  t2.myid = 2
    

    【讨论】:

      猜你喜欢
      • 2018-12-12
      • 1970-01-01
      • 1970-01-01
      • 2020-10-30
      • 2023-04-10
      • 1970-01-01
      • 2013-02-25
      • 1970-01-01
      • 2015-04-15
      相关资源
      最近更新 更多