请考虑下面的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行。那是不对的。如果只删除“和bvc_Order.OrderSource = 56”这个部分,它会返回5行,这是非常正确的。奇怪.另一件事,如果我移除这个部分
OR bvc_OrderItem_BundleItem.ProductID IN ('28046_00')
它还将像预期的那样返回5行,即使使用bvc_Order.OrderSource过滤器。我不知道它为什么要添加更多的行,而我试图通过使用过滤器来减少行。
表bvc_OrderItem_BundleItem不包含结果顺序ids或OrderItemID的任何行
编辑
谢谢各位,我尝试删除左/右连接混合,但是查询管理器不允许只允许左连接,它至少添加了一个右连接。我更新了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;
editSo远没有解决这个问题的办法。我以前在我的注释中粘贴了一个链接,并为带有查询的有效/无效结果提供了示例数据。又来了。http://sameers.me/SQLIssue.xlsx
这里要记住的一件事是,所有剩下的联接都是不可能的。让我进一步解释一下,bvc_Order包含主订单记录,bvc_ORderItem包含订单项/产品,bvc_ORderItem_BundleItem包含产品的子产品,这些产品在bvC_OrderItem表中可用。
现在并不是每个产品都有子产品,所以bvc_OrderItem_BundleItem可能没有任何记录(在当前的场景中,bvC_OrderItem_BundleItem中的订单实际上没有有效的行)。简而言之,在当前场景中,bvc_OrderItem_BundleItem表中没有可用的匹配行。如果我现在删除那个联接,这一切都没问题,但是在现实世界中,我当然不能删除那个BundleItem表联接。
谢谢
发布于 2016-03-22 02:11:12
当你说
WHERE bvc_Order.OrderSource = 56
当bvc_Order.OrderSource
为NULL
时,计算结果为false。如果LEFT/RIGHT
连接失败,那么它将是NULL
。这有效地将LEFT/RIGHT
连接转换为内部连接。
您可能应该将谓词写入ON
子句。另一种可能产生不同结果的办法是:
WHERE (bvc_Order.OrderSource IS NULL OR bvc_Order.OrderSource = 56)
其他谓词也有相同的问题:
另外,如果我移除部件
OR bvc_OrderItem_BundleItem.ProductID IN ('28046_00')
,它也将按预期返回5行
当连接失败时,bvc_OrderItem_BundleItem.ProductID
是NULL
。
我还建议手动编写查询。如果我理解正确的话,这个查询来自一个设计人员。它的结构很混乱。我要提一个最重要的评论:
在查询中混合左和右外部联接只是令人困惑。首先,应该重写from子句,使其只使用一种类型(我强烈建议左外部联接)。-戈登·林诺夫
发布于 2016-03-28 20:41:17
当你消除了不可能的东西,剩下的,无论多么不可能,都是真理吗?S.H.
附加于WHERE子句的附加条件不可能导致额外的行。这将意味着数据库引擎的缺陷,我希望我可以假设这是“不可能的”。(如果不是,那么我想它又回到了原点)。
这一事实使人们更容易集中精力于可能的原因:
发布于 2016-03-22 03:31:19
当您使用左外部联接时,当您的和或条件满足时,它将给出左表(dbo.bvc_OrderItem)中的所有行,右侧外部联接也会发生相同的情况,
这些条件(左联接、右联接)可能不限制行,因为一个表中的行可以全部,另一个表只有一些行。
检查您的加入条件
然后检查你的情况:
(bvc_Order.StatusCode <> 1和bvc_Order.StatusCode <> 999)如果任何符合这个条件的行下一次检查另一个条件bvc_OrderItem.ProductID IN ('28046_00')或bvc_OrderItem_BundleItem.ProductID IN ('28046_00')
那么bvc_Order.OrderSource = 56
比较三个查询的结果,并根据条件检查数据,然后编写完整的查询,这样您就可以了解您所犯的错误。
https://stackoverflow.com/questions/36082594
复制相似问题