了解 SQL 别名

Understanding an SQL Alias

我是 SQL 的新手。 我读过名为 'Sams Teach Yourself Oracle PL/SQL in 10 minutes' 的书。 我发现它非常有趣且易于理解。有一些关于别名的信息,但是当我开始做练习时,我遇到了一个我不知道其用途的别名。

这是引用 http://www.sql-ex.ru/ and here is the database schema http://www.sql-ex.ru/help/select13.php#db_1,以防万一。我正在使用计算机公司数据库,即数据库编号 1。任务是:

找到生产 PC 但不生产笔记本电脑的制造商。

这是解决方案之一:

SELECT DISTINCT maker
           FROM Product AS pcproduct
          WHERE type = 'PC' 
            AND NOT EXISTS (SELECT maker
                              FROM Product
                             WHERE type = 'laptop' 
                               AND maker = pcproduct.maker
                           );

问题是:为什么我们需要将产品别名为pc_product并在子查询中进行比较'maker = pc_product.maker'?

因为在内部查询中有一些列,它们的名称与外部查询中的完全相同(因为您在那里使用相同的table)。

既然内层查询中有外层查询列,那肯定是有区别的,你要哪一列,不用别名,你在内层查询中写maker = maker,这样就永远成立了。

该查询可以理解为:

Gimme the maker's that have products of the 'PC' type, but where a product of the 'laptop' type doesn't exist for that maker.

当超过 1 个 table.
使用相同的列名时,有时需要包含 table 名称或别名 这样优化器就会知道从哪个 table 使用该列。

不是一些聪明的 AI 可以猜出一个标准
WHERE x = x
实际上意味着
WHERE table1.x = table2.x

但更常见的是使用更短的别名。
增加可读性并使 SQL 更简洁。

例如。下面两个查询是等价的。

没有别名:

SELECT myawesometableone.id, mysecondevenmoreawesometable.id, 
       mysecondevenmoreawesometable.col1
FROM myawesometableone
JOIN mysecondevenmoreawesometable on mysecondevenmoreawesometable.one_id = myawesometableone.id

别名:

SELECT t1.id, t2.id, t2.col1
FROM myawesometableone AS t1
JOIN mysecondevenmoreawesometable AS t2 on t2.one_id = t1.id

你觉得哪个SQL更好看?

至于EXISTS里面为什么要用maker = pc_product.maker
这就是 EXISTS 语法的工作原理。
您在 EXISTS 中的查询和外部查询之间建立 link。
在这种情况下,link 是 "maker" 列。

这不会影响其他(正确)答案,但更容易理解的示例可能是:

SELECT DISTINCT pcproduct.maker
           FROM Product AS pcproduct
          WHERE pcproduct.type = 'PC' 
            AND NOT EXISTS (SELECT internalproduct.maker
                              FROM Product AS internalproduct
                             WHERE internalproduct.type = 'laptop' 
                               AND internalproduct.maker = pcproduct.maker
                           );

您正在访问 table 两次,一次在主查询中,一次在子查询中。

在主查询中你说:查看每条记录。如果类型不等于 'PC',请忽略它。如果您在 table 中找到类型为 'laptop'.

的同一制造商的记录,请忽略它

为了查询相同的制造商,您必须将主查询记录的制造商与子查询的记录进行比较。两者都来自同一个 table,因此 where product.maker = product.maker 会产生歧义。 (或者更确切地说,DBMS 会假设您正在谈论子查询记录,因为表达式在子查询中。因此 where product.maker = product.maker 为真,您最终只检查是否有至少一台笔记本电脑table,与制造商无关。)

因此,当在一个查询中两次处理相同的 table 时,至少要给其中一个别名,以便将一条记录与另一条记录区分开来。

无论如何,对于给定的查询,我还要限定表达式中的另一列以提高可读性:

AND product.maker = pcproduct.maker

甚至

 FROM Product laptopproduct
WHERE type = 'laptop' 
  AND laptopproduct.maker = pcproduct.maker

旁注:该查询查找生产 PC 但不生产笔记本电脑的制造商。我更喜欢通过聚合来请求这个:

select maker
from product
group by maker
having sum(type = 'PC') > 0
   and sum(type = 'laptop') = 0;