在SQL中,何时需要给表名起别名?

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

有人能解释一下这个吗?
6个回答

8
您在查询中两次使用了相同的表Purchases。您需要通过给它们不同的名称来区分它们。
您需要提供一个别名:
当多次引用相同的表名时,可以想象有两个完全相同的John Doe。如果您叫John,两个人都会回应您的呼叫。您不能给两个人相同的名字并假设他们会知道您在叫谁。同样,当您给出完全相同的结果集名称时,SQL无法确定从哪个结果集中获取值。您需要给它们不同的名称以区分结果集,这样SQL引擎就不会混淆。
脚本1:t1和t2是此处的别名名称。
SELECT      t1.col2
FROM        table1 t1
INNER JOIN  table1 t2
ON          t1.col1 = t2.col1
  • 当有派生表/子查询输出时

如果一个人没有名字,你称呼他们,但由于你不能叫那个人,他们不会回应你。同样地,当你生成一个派生表输出或子查询输出时,它对于SQL引擎来说是未知的,它不知道该怎么称呼它。所以,你需要给这个派生输出一个名字,以便SQL引擎可以适当地处理这个派生输出。

脚本2t1 是这里的别名。

SELECT col1
FROM
(
    SELECT col1
    FROM   table1
) t1

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引擎会困惑于您是指第一个purchases表还是第二个purchases表。
通过添加别名,您现在通过更加明确来消除歧义。 SQL引擎现在可以确定您要使用哪个版本的purchases,并且可以100%确定。如果它必须在两个相等的选择之间猜测,则始终会引发错误并要求您更加明确。

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

谢谢Dave,哦,那个解决方案不错,我之前没想到过! - tim peterson

1

在查询中两次使用同一张表时,必须为它们命名。在您的情况下,查询不知道应该从哪个表中选择 purchases.purchase_date。


1

别名是必要的,以消除从哪个表中获取列的歧义。

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

如果该列的名称在from列表中的多个表中重复出现,则DB服务器无法猜测获取该列的正确表。

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

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


0

在同一查询中,除非将其别名为其他内容以防止模糊的连接条件,否则不能在相同的查询中使用相同的表格名称。这就是为什么不允许的原因。我应该指出,最好总是限定表格.字段或别名.字段,以便在你后面的其他开发人员不必猜测哪些列来自哪些表格。

编写查询时,你知道自己在处理什么,但是对于在你后面的开发人员来说又是如何呢?如果有人不熟悉哪些列来自哪个表,那么跟随可能会存在歧义,特别是在 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

如果你必须保留联接或字段列的限定条件,你更喜欢看哪一个?

希望这样能澄清你的问题。


嗨DRapp,谢谢你。我对你的句子“……始终使用限定器table.field更好……”有点困惑。你能详细说明一下吗? - tim peterson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接