【发布时间】:2016-04-01 01:49:15
【问题描述】:
考虑下面的 SQL。
SELECT DISTINCT bvc_Order.ID,
bvc_OrderItem.ProductID,
bvc_OrderItem_BundleItem.ProductID
FROM dbo.bvc_OrderItem WITH (nolock)
RIGHT OUTER JOIN dbo.bvc_Order WITH (nolock)
LEFT OUTER JOIN dbo.bvc_User WITH (nolock) ON dbo.bvc_Order.UserID = dbo.bvc_User.ID
LEFT OUTER JOIN dbo.Amazon_Merchants WITH (nolock) ON dbo.bvc_Order.CompanyID = dbo.Amazon_Merchants.ID ON dbo.bvc_OrderItem.OrderID = dbo.bvc_Order.ID
LEFT OUTER JOIN dbo.bvc_OrderItem_BundleItem WITH (nolock) ON dbo.bvc_OrderItem.ID = dbo.bvc_OrderItem_BundleItem.OrderItemID
LEFT OUTER JOIN dbo.bvc_Product WITH (nolock) ON dbo.bvc_OrderItem.ProductID = dbo.bvc_Product.ID
WHERE 1=1
AND (bvc_Order.StatusCode <> 1
AND bvc_Order.StatusCode <> 999)
AND ( bvc_OrderItem.ProductID IN ('28046_00')
OR bvc_OrderItem_BundleItem.ProductID IN ('28046_00'))
AND bvc_Order.OrderSource = 56;
当我对我的数据库执行查询时,它返回 85 行。嗯,这是不正确的。 如果我只是删除部分“AND bvc_Order.OrderSource = 56”,它会返回 5 行,这确实是正确的。 奇怪的..... 另一件事,如果我删除部分
OR bvc_OrderItem_BundleItem.ProductID IN ('28046_00')
即使使用 bvc_Order.OrderSource 过滤器,它也会按预期返回 5 行。 我不确定为什么在我尝试使用过滤器减少行时它会添加更多行。
表 bvc_OrderItem_BundleItem 不包含结果订单 ID 或 OrderItemID 的任何行
[编辑]
谢谢大家,我尝试删除 LEFT/RIGHT Join Mix,但查询管理器不仅允许 LEFT,它确实添加了至少一个 RIGHT 连接。我更新了 SQL 以删除额外的表,现在我们只有三个。但是结果一样
SELECT DISTINCT dbo.bvc_Order.ID, dbo.bvc_OrderItem.ProductID, dbo.bvc_OrderItem_BundleItem.ProductID AS Expr1
FROM dbo.bvc_OrderItem
LEFT OUTER JOIN dbo.bvc_OrderItem_BundleItem ON dbo.bvc_OrderItem.ID = dbo.bvc_OrderItem_BundleItem.OrderItemId
RIGHT OUTER JOIN dbo.bvc_Order ON dbo.bvc_OrderItem.OrderID = dbo.bvc_Order.ID
WHERE 1=1
AND (bvc_Order.StatusCode <> 1 AND bvc_Order.StatusCode <> 999)
AND (
bvc_OrderItem.ProductID IN ('28046_00')
OR bvc_OrderItem_BundleItem.ProductID IN ('28046_00')
)
AND bvc_Order.OrderSource = 56;
[编辑]到目前为止,还没有解决方案。我之前在我的评论中粘贴了一个链接,其中包含带有查询的有效/无效结果的示例数据输出。又来了。 http://sameers.me/SQLIssue.xlsx
这里要记住的一件事是,ALL left join 是不可能的。让我进一步解释 bvc_Order 包含主订单记录 bvc_ORderItem 包含订单项目/产品 bvc_ORderItem_BundleItem 包含产品的子产品,在 bvC_OrderItem 表中可用。
现在不是每个产品都有子产品,所以 bvc_OrderItem_BundleItem 可能没有任何记录(在当前场景中,bvC_OrderItem_BundleItem 中的订单确实没有有效行)。 简而言之,在当前情况下,bvc_OrderItem_BundleItem 表中没有可用的匹配行。如果我现在删除那个连接,一切都好,但在现实世界中,我当然不能删除那个 BundleItem 表连接。
谢谢
【问题讨论】:
-
在查询中混合左右外连接只是令人困惑。您应该首先重写
from子句以仅使用一种类型(我强烈推荐left outer join)。 -
摆脱现在(过去 10 年开始)不好的做法(nolock)。编写并格式化它,并在SQL Fiddle 中放置一个带有数据的示例,这样我们就可以找到这里发生的事情。根据我的经验,奇怪的行为来自糟糕的书面查询,引擎只是尝试按照您的指示去做。
-
使用
WITH (NOLOCK)可能会提供微不足道的性能提升,但您的查询结果将不可靠。 -
我不明白您为什么不能更改自己的代码(删除右连接)?你不是在编写这个 SQL 查询吗?
-
请在评论中运行您的“使用所有左连接的更新查询”,并将 5 条正确的结果记录和 85 条错误的结果记录发布到您的问题中。其他 80 条记录不正确的原因是什么?
标签: sql sql-server sql-server-2008