我注意到在使用多个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
有人可以解释一下吗?
答案 0 :(得分:6)
您在查询中使用相同的表购买两次。您需要通过提供不同的名称来区分它们。
您需要提供别名:
When the same table name is referenced multiple times
强> 想象一下两个人拥有完全相同的John Doe。如果你打电话给John,他们都会回应你的电话。你不能给两个人同名,并假设他们会知道你在跟谁打电话。类似地,当您为相同的结果集提供完全相同的结果集时,SQL无法识别从中获取值的结果集。您需要提供不同的名称来区分结果集,以便SQL引擎不会混淆。
脚本1 : t1 和 t2 是此处的别名
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引擎可以适当地处理派生的输出。
脚本2 : t1 是此处的别名。
SELECT col1
FROM
(
SELECT col1
FROM table1
) t1
答案 1 :(得分: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%确定地说您要使用哪个版本的购买。如果它必须在两个相同的选择之间猜测,那么它总是会抛出一个错误,要求你更明确。
答案 2 :(得分:1)
在查询中使用两次相同的表时,需要为它们指定名称。在您的情况下,查询将不知道从哪个表中选择purchase.purchase_date。
答案 3 :(得分: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
答案 4 :(得分:1)
别名对于消除从中获取列的表的歧义是必要的。
因此,如果列的名称在from列表中的表中可用的所有可能列的列表中是唯一的,那么您可以直接使用coulmn名称。
如果在列表中的几个表中重复了列的名称,那么数据库服务器无法猜测哪个是获取列的正确表。
在您的示例查询中,所有列名称都是重复的,因为您正在获取同一个表(购买)的“两个实例”,因此服务器需要知道要从哪个实例获取该列。所以你必须指定它。
事实上,我建议你总是使用别名,除非有一个表。通过这种方式,您可以避免许多问题,并使查询更加清晰易懂。
答案 5 :(得分:0)
您不能在同一个查询中使用相同的表名,除非它是别名以防止出现模糊的连接条件。这就是为什么它不被允许。我应该注意,使用always qualify 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
如果您必须保留符合条件的联接或字段列,那么您更愿意查看。
希望这能澄清你的问题。