在下面的查询中,当我有两个左连接时,我遇到了麻烦。会发生什么是两个左连接的总和不正确(提升)。当我删除第二个左连接时,查询正确运行。如何使用第二个左连接运行此查询?
SELECT o.IdNoLocation,
COUNT(DISTINCT o.EncodedId) AS "Frequency",
ISNULL(SUM(o.Subtotal), 0) AS "Spend",
ISNULL(SUM(os.Amount), 0) AS "Surcharges",
ISNULL(SUM(od.Amount), 0) AS "Discounts"
FROM ((tblOrder o
LEFT JOIN tblOrderSurcharge os ON o.OrderId=os.OrderId)
LEFT JOIN tblOrderDiscount od ON o.OrderId=od.OrderId)
WHERE
o.BusinessDate BETWEEN '2014-01-01' AND '2014-12-31'
AND o.IdNoLocation <> 'X'
GROUP BY o.IdNoLocation
答案 0 :(得分:0)
当tblOrderSurcharge
或tblOrderDiscount
中有多个相关行时,这是预期的结果...您在这两个表的行之间有一个隐式的半交叉连接。
如果你需要在一个声明中返回的总数,有几种“修复”这种方法。
一种选择是使用内联视图执行总计,然后组合行。实质上,运行单独的查询以从每个表中获取总计,然后将结果组合在唯一键上。例如:
SELECT o.IdNoLocation
, o.Frequency
, ISNULL(o.Spend, 0) AS Spend
, ISNULL(s.Surcharges), 0) AS Surcharges
, ISNULL(s.Discounts), 0) AS Discounts
FROM ( SELECT ooo.IdNoLocation
, COUNT(DISTINCT ooo.EncodedId) AS Frequency
, SUM(ooo.Subtotal) AS Spend
FROM tblOrder ooo
WHERE ooo.BusinessDate BETWEEN '2014-01-01' AND '2014-12-31'
AND ooo.IdNoLocation <> 'X'
GROUP BY ooo.IdNoLocation
) o
LEFT
JOIN ( SELECT oso.IdNoLocation
, SUM(oss.Amount) AS Surcharges
FROM tblOrderSurcharge oss
JOIN tblOrder oso
ON oso.OrderId = oss.OrderId
WHERE oso.BusinessDate BETWEEN '2014-01-01' AND '2014-12-31'
AND oso.IdNoLocation <> 'X'
GROUP BY oso.IdNoLocation
) s
ON s.IdNoLocation = o.IdNoLocation
LEFT
JOIN ( SELECT odo.IdNoLocation
, SUM(odd.Amount) AS Discounts
FROM tblOrderDiscount odd
JOIN tblOrder odo
ON odo.OrderId = odd.OrderId
WHERE odo.BusinessDate BETWEEN '2014-01-01' AND '2014-12-31'
AND odo.IdNoLocation <> 'X'
GROUP BY odo.IdNoLocation
) d
ON d.IdNoLocation = o.IdNoLocation
(这不经过测试,只需检查桌面。运行每个内联视图查询(o,s,d)并验证每个查询的结果是否符合预期。然后,运行整个查询,合并行...在外部查询中,我们将执行“外部”连接并处理“缺失”行并用零替换NULL)
另一种选择是在SELECT列表中使用相关子查询。
答案 1 :(得分:0)
要了解为什么这不起作用,请运行此查询:
SELECT o.IdNoLocation,
o.EncodedId AS "Frequency",
o.Subtotal AS "Spend",
os.Amount AS "Surcharges",
od.Amount AS "Discounts"
FROM ((tblOrder o
LEFT JOIN tblOrderSurcharge os ON o.OrderId=os.OrderId)
LEFT JOIN tblOrderDiscount od ON o.OrderId=od.OrderId)
WHERE
o.BusinessDate BETWEEN '2014-01-01' AND '2014-12-31'
AND o.IdNoLocation <> 'X'
&#39;正确&#39;答案是使用一张表来收取附加费和折扣。我认为这不再是一个选项,但你可以使用在两个表之间执行UNION ALL的视图来伪造它。