【问题标题】:LEFT JOIN returns duplicate SUM valuesLEFT JOIN 返回重复的 SUM 值
【发布时间】:2021-09-12 00:11:56
【问题描述】:

我有以下表格:

create table Invoices
(
  InvoiceID int,
  InvoiceNumber int,
  InvoiceDate date,
  SupplierName varchar(250),
  SupplierCode varchar(20),
  InvoiceValue decimal(18,2)  
);

insert into Invoices (InvoiceID, InvoiceNumber, InvoiceDate, SupplierName, SupplierCode, InvoiceValue) values 
(1,700,'2021-01-01','ACME','A01',978.32),
(2,701,'2021-01-02','MACROD','A02',772.81),
(3,702,'2021-01-03','CODECO','A03',938.20),
(4,703,'2021-01-04','ACME','A03',892.18),
(5,704,'2021-01-05','CODECO','A03',791.41),
(6,705,'2021-01-06','DRONIX','A04',469.03);

create table Payments
(
  InvoiceID int,
  PaymentDate date,  
  PaymentValue decimal(18,2)   
);

insert into Payments (InvoiceID, PaymentDate, PaymentValue) values 
(1, '2021-01-11', 500.00),
(1, '2021-01-12', 50.00),
(1, '2021-02-13', 100.00),
(3, '2021-02-14', 10.00),
(4, '2021-03-15', 200.00),
(3, '2021-03-16', 300.00),
(5, '2021-04-17', 75.00),
(1, '2021-04-18', 30.00);

这是我正在使用的查询:

SELECT
      a.SupplierName, 
      a.SupplierCode, 
      SUM(a.TotalInvoiceValue), 
      ISNULL(SUM(b.PaidAmount), 0), 
      SUM(a.TotalInvoiceValue) - ISNULL(SUM(b.PaidAmount), 0)
FROM (
    SELECT
      InvoiceID,
      SupplierName,
      SupplierCode,
      SUM(InvoiceValue) AS TotalInvoiceValue
    FROM Invoices  
    WHERE InvoiceDate BETWEEN '2021-01-01 00:00:00' AND '2021-01-31 23:59:29'
    GROUP BY
      InvoiceID,
      SupplierName,
      SupplierCode
) a 
LEFT JOIN (
    SELECT
      InvoiceID,
      ISNULL(SUM(PaymentValue),0) AS PaidAmount
    FROM Payments
    GROUP BY InvoiceID
) b 
    ON a.InvoiceID=b.InvoiceID 
GROUP BY
  a.InvoiceID,
  a.SupplierName,
  a.SupplierCode
ORDER BY
  a.SupplierName

上面的查询从 Payments 表中返回了同一个 SupplierName 的多行。

我使用的是 Microsoft SQL Server 2005。

查看 SQL 小提琴here

【问题讨论】:

  • 提醒:SQL Server 2005 已经完全不支持大约 5 年了。它存在已知的安全问题,并且根本不支持许多在较新版本上被视为理所当然的语法。您真的应该尽快查看升级路径。
  • 事实上,您确定您使用的是 2005 年吗? VALUES 表结构是在 SQL Server 2008 中引入的。
  • 通常在 GROUP BY 子句中包含未出现在 SELECT 列表中的列表明您想要的目标与您的查询不完全匹配。那么你的结果集代表什么?按 InvoiceID 分组意味着您在 invoice 级别请求信息,但您的选择列表意味着您需要供应商级别的值。而且您还遇到了同一供应商具有多个代码的附加问题。明确那个目标。你的输出应该基于样本数据吗?
  • @SMor,最终结果应该是每个供应商的清单及其发票价值和收到的付款,就像我现在得到的查询结果一样,但按供应商分组。
  • 空白不花钱,你知道的。如果您使用的是更高版本,则可以删除该 left join 并将其替换为第一个表上的窗口聚合 ISNULL(SUM(SUM(b.PaidAmount)) OVER (PARTITION BY InvoiceID), 0)

标签: sql-server group-by sql-server-2005 sum left-join


【解决方案1】:

由于您按(a.InvoiceID、a.SupplierName、a.SupplierCode)分组,因此发票 ID、供应商名称和供应商代码的每个组合都有不同的记录。尝试按您的选择语句中的非聚合字段分组以返回不同的汇总行(在这种情况下,不要按发票 ID 分组,因为它不在您的选择语句中)。

在这种情况下,您选择 SupplierName 和 SupplierCode。这将复制每个供应商代码的供应商名称。如果您想要 SupplierName 的独特摘要记录,请不要选择供应商代码。

使用供应商代码

SELECT a.SupplierName, 
  a.SupplierCode, 
  SUM(a.TotalInvoiceValue), 
  ISNULL(SUM(b.PaidAmount),0), 
  SUM(a.TotalInvoiceValue)-ISNULL(SUM(b.PaidAmount),0)
FROM 
  (SELECT InvoiceID, SupplierName, SupplierCode, SUM(InvoiceValue) AS TotalInvoiceValue FROM Invoices  
  WHERE InvoiceDate BETWEEN '2021-01-01 00:00:00' AND '2021-01-31 23:59:29' 
  GROUP BY InvoiceID, SupplierName, SupplierCode) a 
LEFT JOIN 
  (SELECT InvoiceID, ISNULL(SUM(PaymentValue),0) AS PaidAmount FROM Payments GROUP BY InvoiceID) b 
ON a.InvoiceID=b.InvoiceID 
GROUP BY a.SupplierName, a.SupplierCode
ORDER BY a.SupplierName

没有供应商代码

SELECT a.SupplierName, 
  SUM(a.TotalInvoiceValue), 
  ISNULL(SUM(b.PaidAmount),0), 
  SUM(a.TotalInvoiceValue)-ISNULL(SUM(b.PaidAmount),0)
FROM 
  (SELECT InvoiceID, SupplierName, SupplierCode, SUM(InvoiceValue) AS TotalInvoiceValue FROM Invoices  
  WHERE InvoiceDate BETWEEN '2021-01-01 00:00:00' AND '2021-01-31 23:59:29' 
  GROUP BY InvoiceID, SupplierName, SupplierCode) a 
LEFT JOIN 
  (SELECT InvoiceID, ISNULL(SUM(PaymentValue),0) AS PaidAmount FROM Payments GROUP BY InvoiceID) b 
ON a.InvoiceID=b.InvoiceID 
GROUP BY a.SupplierName
ORDER BY a.SupplierName

【讨论】:

  • 谢谢,安德鲁!删除“a.InvoiceID”正是我需要查询返回所需结果(仅按供应商名称和代码分组)
猜你喜欢
  • 2020-06-10
  • 2013-11-28
  • 1970-01-01
  • 2013-09-28
  • 2012-03-27
  • 2018-12-15
  • 1970-01-01
  • 2021-11-21
  • 2021-10-19
相关资源
最近更新 更多