想要了解我正在尝试剖析的视图的查询

问题描述 投票:3回答:2

我对我正在使用的一些查询感到困惑。

select *
from Table1
inner join Table2
  on Table1.id1 = Table2.id1
right outer join Table3
right outer join Table4
inner join Table5
  on Table4.id1 = Table5.id1
  on Table3.id1 = Table5.id2
  on Table1.id2 = Table5.id3

我试图让查询尽可能接近我正在使用的内容。

我不理解没有ON的连接,然后连接多个ON。在表5加入之前,表3和表4是否实际上没有连接?

以下不起作用,因为Table5.id1和Table5.id2接收'多部分标识符'Table5.id_“无法绑定

select *
from Table1
inner join Table2
  on Table1.id1 = Table2.id1
right outer join Table3
  on Table3.id1 = Table5.id2
right outer join Table4
  on Table4.id1 = Table5.id1
inner join Table5
  on Table1.id2 = Table5.id3

此外,这个位确实处理,因为表5首先连接并解决了边界错误,但我收到的记录比想要的多大约27k

select *
from Table1
inner join Table2
  on Table1.id1 = Table2.id1
inner join Table5
  on Table1.id2 = Table5.id3
right outer join Table3
  on Table3.id1 = Table5.id2
right outer join Table4
  on Table4.id1 = Table5.id1

所以在这一点上很明显原始查询是按原因构建的,但我仍然不理解它背后的逻辑或实际发生的事情。

任何帮助将非常感激。

sql sql-server
2个回答
1
投票

你在这里有多个嵌套连接。在我解释之前,我将稍微重新格式化查询,以便更容易看到发生了什么。

select *
from Table1
inner join Table2 on Table1.id1 = Table2.id1
right outer join Table3 -- Join B
    right outer join Table4 -- Join A
        inner join Table5 on Table4.id1 = Table5.id1
    on Table3.id1 = Table5.id2 -- ON clause for Join A
on Table1.id2 = Table5.id3 -- ON clause for Join B

嵌套连接允许您将两个表连接在一起,然后将该结果连接到另一组记录。最初这听起来并不十分有用。那只是一次定期加入,对吗?均田。不同之处在于,只有当最内层连接成功时,它才会尝试将该行连接到外部表。如果您正在使用内部联接,那么这根本不是很有用。如果你正在混合内部和外部连接,那么它会变得更加有趣(稍后会详细介绍)。

我将尝试用散文和评论来解释这个查询的内容,所以希望两者之间有意义。

首先,这里最内部的连接是表4和5之间的内部连接。这些表首先连接在一起。这将为您提供一个结果集,其中Table4中的每一行在表5中至少有一个匹配的行(根据on子句中存在的任何条件,在本例中为Table4.id1 = Table5.id1)。这隐式地过滤掉Table4和Table5中在另一个表中没有匹配的任何行。

然后,该结果右键连接到Table3(在Table3.id1 = Table5.id2上)。这意味着您将获得Table3中的所有记录以及Table4 / 5连接集中的相应匹配(如果存在)。

然后我们使用表1(在qazxsw poi上)对整个结果集进行右连接。这意味着我们最终将表3中的所有内容加入表4/5组合,然后加入表1/2组合。

最终结果集是Table3连接的所有内容,其中0行或多行与Table1和Table2匹配(如果Table1没有匹配的Table2记录,则不会连接到Table3)。表4/5也是如此。我相信这是正确的(如果没有运行查询的能力,太过盯着它意味着我可能会弄糊涂自己,但基本的想法是正确的)。

为什么这个疯狂的语法呢?替代品也是一种痛苦。您可以使用CTE或Table3.id1 = Table5.id2语句,这两种语句都是他们自己的乐趣(不一定很难,只是不是你的香草SQL。我尝试使用那些转换你的查询,我觉得我相当接近,然后我把自己困在一个角落里因为对事物的命名不好然后我放弃了)。那么为什么呢?嗯,这意味着只有在前两个表中存在匹配项时,才能确保可以将两个表外连接到第三个表。也许一个更具体的例子会有所帮助?

假设你有4张桌子applyPersonOrderOrderItem。您的任务是返回显示每个订单的结果集,并突出显示包含Figlewubbit的订单以及在其上使用折扣代码的订单。所以你写这个:

OrderItemDiscount

写它的另一种方法是:

select *
from Person p
left join Order o on o.PersonId = p.PersonId
left join OrderItem oi on oi.OrderId = o.OrderId
                          and oi.ItemName = 'Figlewubbit'
left join OrderItemDiscount oid on oid.OrderItemId = oi.OrderItemId

这里的执行计划将会改变。 select * from Person p left join Order o on o.PersonId = p.PersonId left join OrderItem oi inner join OrderItemDiscount oid on oid.OrderItemId = oi.OrderItemId on oi.OrderId = o.OrderId and oi.ItemName = 'Figlewubbit' OrderItem将加入到一起,然后该组将被送入左边加入OrderItemdDiscount。每个OrderOrderItem连接行都被有效地视为其他连接的组合实体。没有另一个你就不会得到一个。

(如果这个例子看起来很糟糕,我很抱歉。嵌套连接是一个奇怪的野兽。它们有它们的用途(我需要它们一次或两次)。但是提出一个需要使用它们的简单例子非常困难。它们非常专门的工具,通常需要一个同样专业(和复杂)的要求,以保证他们的使用。我强烈建议首先研究这个,并使用它们的简单版本。组合正确的连接和多个嵌套连接甚至让我头疼试图解析它。 )


0
投票

实际上,首先连接表4和5,然后连接表3。这是执行计划:

OrderItemdDiscount

© www.soinside.com 2019 - 2024. All rights reserved.