【问题标题】:SQL wrong sum when using join [closed]使用连接时的SQL错误总和[关闭]
【发布时间】:2026-01-06 09:15:01
【问题描述】:

我有这个问题:

SELECT     BLI.EmpID, ShortEmployees.EmpName1 AS EmpName, SUM(BLI.FinalValue) AS Total
FROM       BLI 
INNER JOIN BSR ON BLI.BLID = BSR.BLID 
INNER JOIN ShortEmployees ON BLI.EmpID = ShortEmployees.EmpID
WHERE     (CONVERT(varchar, BLI.BLDate, 112) >= CONVERT(varchar, CONVERT(datetime, '1/10/2012', 103), 112)) 
AND (CONVERT(varchar, BLI.BLDate, 112)  <= CONVERT(varchar, CONVERT(datetime, '30/10/2012', 103), 112)) 
AND (BSR.BSTID = 2) 
AND (BLI.State IN (2, 6, 8, 9, 10, 12, 18))
GROUP BY BLI.EmpID, ShortEmployees.EmpName1
ORDER BY Total DESC

我预计总数为 42,但我得到了 126 的三倍!

编辑: 我的期望是错误的,查询返回正确的总和。

【问题讨论】:

  • 检查连接。也许您希望在 BSR 中为该 BLID 找到一行,它们是 3。
  • 您使用的是哪个 DBMS?我想了解一下 CONVERT 函数在您的 DBMS 中的作用。
  • @Colin'tHart,SQLServer。 convert 做一个到目前为止的转换字符串。
  • 我使用的是 SQLServer 2008,BLID 是 BSR 的主键,所以不可能有 3 个相同的行值。
  • @mhdali - 从这里的 cmets 和下面的问题来看,你现在是不是说 126 真的是正确的结果,而且一开始就没有问题?

标签: sql sql-server join sum


【解决方案1】:

BSR 包含与 BLI.BLID 匹配的三个记录,或者 ShortEmployees 包含与 BLI.EmpID 匹配的三个记录。

另外,您为什么要将日期转换为 varchar?看起来他们一开始都是约会对象。将您的硬编码日期从“1/10/2012”替换为“2012-10-01”的 ansi 标准

【讨论】:

  • 强烈的 AMEN 到“为什么要将日期转换为 varchar?”为了在任何 DBMS 中获得最佳性能,请始终比较其本机格式的数据类型。然后 DBMS 知道 2012-04-01 紧跟在 2012-03-31 之后,没有可能的中间值,而作为字符串,中间有许多可能的值。
  • @tobsey,不知道为什么用户应该将字符串日期 'British/French' 转换为字符串日期 'ansi',更改为 datetime 格式更有意义。另外,也许您应该等待 OP 回复 cmets。
  • @danihp 该问题包含英国格式的硬编码日期。然后他的数据库中的每个日期都被转换为 varchar。正如科林上面所说,这是非常糟糕的做法。如果提问者将日期作为字符串文字添加到查询中,那么他应该使用正确的格式。
  • BSR.BLID 和 ShortEmployees.EmpID 是他们表的主键,所以……他们有区分值。
  • @Mhdali BSR.BLID 是主键吗? BLID 不是 BLI 的主键,BSR.BLID 不是引用 BLI.BLID 的外键。我建议您删除 SUMGROUP BY 语句并选择所有行和所有列。这将向您显示数据在何处相乘。您可能会发现其中一张表被连接了 3 次。
【解决方案2】:

关于日期格式。对于 SQL Server,请使用此日期格式“YYYYMMDD”。 SQL Server 知道如何将此日期与表中的日期列进行比较。

所以, 正确的 SQL 代码可能是这样的:

WHERE BLI.BLDate &gt;= '20121001' AND BLI.BLDate &lt;= '20121030'

WHERE BLI.BLDate BETWEEN '20121001' AND '20121030'

【讨论】: