【问题标题】:JOIN results give duplicate rows - SQL ServerJOIN 结果给出重复的行 - SQL Server
【发布时间】:2017-11-07 11:25:47
【问题描述】:

我目前正在处理一个未按照我认为应该的方式设置的数据库。几乎没有任何主键/外键,因此连接表可能非常棘手。

我试图重新创建一个与我创建的连接导致不正确重复行的问题类似的问题,这是缺少键的结果。

sql 小提琴 - http://sqlfiddle.com/#!9/ff59ad/1

查询:

SELECT I.InvoiceNumber, I.AmountPaid,
O.Amount
FROM OrderInvoice O
JOIN Invoice I 
ON O.InvoiceNumber = I.InvoiceNumber

现在您可以看到发票编号有重复条目

InvoiceNumber   AmountPaid  Amount
    123           10          8
    123           10          2
    567           10          4
    567           10          6

每个支付的总金额应该是 10,而由于匹配的行,连接会为每个创建 20。因此,如果我将这些结果分组并将它们相加,那么总金额是错误的。它与我的现实生活示例略有不同,因为由于重复的行,即使使用正常的连接语法,我实际上也得到了交叉连接。

删除这些重复行的最佳方法是什么?我已尝试加入多个列以创建唯一行,但我没有其他列可加入。

谁能给我建议?

【问题讨论】:

  • 如果按组求和,总金额怎么会出错??
  • 不,这是完全正常的 - 如果您将单个“标题”记录连接到多个“子”记录,则“标题”记录会针对每个子记录表示。这是一个完全正常的连接操作,也是一个发票抬头连接到多个发票行的完全正常的结果。你到底想在这里做什么?

标签: sql sql-server join


【解决方案1】:

只需添加group by 子句和sum 聚合函数

SELECT I.InvoiceNumber, I.AmountPaid,
sum(O.Amount) Amount
FROM OrderInvoice O
JOIN Invoice I 
ON O.InvoiceNumber = I.InvoiceNumber group by I.InvoiceNumber, I.AmountPaid

结果:

InvoiceNumber   AmountPaid  Amount
123             10          10
567             10          10

【讨论】:

    【解决方案2】:

    试试这个:

    SELECT DISTINCT I.InvoiceNumber, I.AmountPaid
    FROM OrderInvoice O
    JOIN Invoice I 
    ON O.InvoiceNumber = I.InvoiceNumber
    

    第二个表中每个InvoiceNumber 有不止一条记录 - 这就是为什么您在最后一组中获得多条记录的原因。

    【讨论】:

      【解决方案3】:

      如果支付的金额在所有行中都是静态的,那么您也需要按此分组,而不是按总和。

      SELECT I.InvoiceNumber, I.AmountPaid, SUM(O.Amount)
      FROM OrderInvoice O
      JOIN Invoice I ON O.InvoiceNumber = I.InvoiceNumber
      GROUP BY I.InvoiceNumber, I.AmountPaid
      

      【讨论】:

        【解决方案4】:

        这样没关系,因为你有不同的金额值

        如果你SUM,金额应该没问题

        SELECT I.InvoiceNumber, I.AmountPaid,
        SUM(O.Amount)
        FROM OrderInvoice O
        JOIN Invoice I 
        ON O.InvoiceNumber = I.InvoiceNumber
        GROUP BY I.InvoiceNumber,I.AmountPaid
        

        【讨论】:

          【解决方案5】:

          当您将table a 加入到table b 时,每场比赛的结果中都会有一行。

          Io 如果table b 有两行与table a 匹配,则表a 中的数据将被复制。第一场比赛一次,第二场比赛一次。

          在您的情况下,OrderInvoice 表中有两行与Invoice 表中的一行匹配。 AmountPaid 来自Invoice 表,因此它将被复制为Invoice 中的单行匹配OrderInvoice 中的两行。

          【讨论】:

            【解决方案6】:

            我想也许你在追求这个:

            SELECT 
            I.InvoiceNumber, 
            I.AmountPaid,
            L.LineTotal
            FROM Invoice O
            JOIN 
            (
            SELECT O.InvoiceNumber, SUM(O.Amount) As LineTotal
            FROM OrderInvoice O
            GROUP BY O.InvoiceNumber
            ) As L
            ON L.InvoiceNumber = I.InvoiceNumber
            

            这会将行预聚合为每个发票编号的单行,然后将其连接到标题中。

            这会给你一个标题级别的数字。

            如果你想要一个线级数字,你需要弄清楚如何处理总数 - 放在第一行? - 放在最后一行? - 划线?

            这些都没有任何意义

            【讨论】:

              猜你喜欢
              • 2014-06-01
              • 1970-01-01
              • 2019-02-16
              • 1970-01-01
              • 1970-01-01
              • 2011-09-15
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多