8

我注意到在使用多个 JOIN 进行查询时,除非我为其中一个表名指定别名,否则我的查询不起作用。

这是一个简单的例子来解释这一点:

不起作用

SELECT subject
from items
join purchases on items.folder_id=purchases.item_id
join purchases on items.date=purchases.purchase_date
group by folder_id

这样

SELECT subject
from items
join purchases on items.folder_id=purchases.item_id
join purchases as p on items.date=p.purchase_date
group by folder_id

有人可以解释一下吗?

4

6 回答 6

8

您在查询中使用了同一个表 Purchases 两次。您需要通过提供不同的名称来区分它们。

您需要提供别名:

  • When the same table name is referenced multiple times

想象一下两个人拥有完全相同的 John Doe。如果您打电话给约翰,双方都会响应您的电话。你不能给两个人相同的名字,并假设他们会知道你在打电话给谁。类似地,当您提供名称完全相同的相同结果集时,SQL 无法识别从哪一个中获取值。您需要给出不同的名称来区分结果集,这样 SQL 引擎就不会混淆。

脚本 1t1t2是这里的别名

SELECT      t1.col2
FROM        table1 t1
INNER JOIN  table1 t2
ON          t1.col1 = t2.col1
  • When there is a derived table/sub query output

如果一个人没有名字,你打电话给他们,因为你不能打电话给那个人,他们不会回复你。同样,当您生成派生表输出或子查询输出时,它是 SQL 引擎未知的,它不会调用什么。因此,您需要为派生输出命名,以便 SQL 引擎可以适当地处理该派生输出。

脚本 2t1是这里的别名。

SELECT col1
FROM
(
    SELECT col1
    FROM   table1
) t1
于 2012-05-03T14:16:37.173 回答
5

唯一需要提供别名的情况是,当您多次引用该表并且您有派生输出(充当表的子查询)时(感谢您发现 Siva)。这样您就可以消除在其余查询中使用哪个表引用之间的歧义。

为了进一步详细说明,在您的示例中:

SELECT subject
from items
join purchases on items.folder_id=purchases.item_id
join purchases on items.date=purchases.purchase_date
group by folder_id

我的假设是您觉得每个join及其对应on的都将使用相关表,但是您可以使用您想要的任何表引用。因此,当您说 时on items.date=purchases.purchase_date,SQL 引擎会混淆您是指第一个购买表还是第二个表。

通过添加别名,您现在可以更明确地消除歧义。SQL 引擎现在可以 100% 确定您要使用哪个版本的购买。如果它必须在两个相等的选择之间进行猜测,那么它总是会抛出一个错误,要求你更明确。

于 2012-05-03T14:15:09.423 回答
1

当同一个表在查询中使用两次时,需要给它们命名。在您的情况下,查询将不知道从哪个表中选择 purchase.purchase_date。

于 2012-05-03T14:15:13.277 回答
1

在这种情况下,只是您指定了两次购买,并且 SQL 引擎需要能够以唯一的方式引用连接中的每个数据集,因此需要别名。

顺便说一句,您真的需要两次参与购买吗?这行不通:

SELECT 
    subject
from 
    items
    join purchases 
        on items.folder_id=purchases.item_id
        and items.date=purchases.purchase_date
group by folder_id
于 2012-05-03T14:16:17.003 回答
1

别名对于消除从中获取列的表的歧义是必要的。

因此,如果列的名称在 from 列表中的表中可用的所有可能列的列表中是唯一的,那么您可以直接使用列名称。

如果列的名称在 from 列表中的几个可用表中重复,则 DB 服务器无法猜测哪个表是获取该列的正确表。

在您的示例查询中,所有列名称都是重复的,因为您获得了同一个表(购买)的“两个实例”,因此服务器需要知道从哪个实例中获取该列。所以你必须指定它。

事实上,我建议您始终使用别名,除非只有一个表。这样您就可以避免很多问题,并使查询更加清晰易懂。

于 2012-05-03T14:18:35.947 回答
0

您不能在同一查询中使用相同的表名,除非它被别名为其他名称以防止不明确的连接条件。这就是为什么它不允许。我应该注意,使用 always qualified table.field 或 alias.field 也更好,这样您后面的其他开发人员就不必猜测哪些列来自哪些表。

编写查询时,您知道自己在处理什么,但您身后的开发人员又如何。如果有人不习惯什么列来自什么表,那么跟随它可能会模棱两可,尤其是在 S/O 中。通过始终使用表引用和字段或别名引用和字段进行限定,它更容易遵循。

select
      SomeField,
      AnotherField
   from
      OneOfMyTables
         Join SecondTable
            on SomeID = SecondID

将其与

select
      T1.SomeField,
      T2.AnotherField
   from
      OneOfMyTables T1
         JOIN SecondTable T2
            on T1.SomeID = T2.SecondID

在这两种情况下,您更喜欢阅读哪一种……请注意,我使用较短的别名“T1”和“T2”简化了查询,但它们可以是任何东西,甚至是表名的首字母缩写词或缩写别名。 .“oomt”(我的一张桌子)和“st”(第二张桌子)。或者,就像其他帖子中的超长内容一样......

Select * from ContractPurchaseOffice_AgencyLookupTable

vs 

Select * from ContractPurchaseOffice_AgencyLookupTable  AgencyLkup

如果您必须保留符合条件的联接或字段列,您更愿意查看哪个。

希望这能澄清你的问题。

于 2012-05-03T14:15:51.043 回答