大多数SQL专家都会说,不能在同一级别的select中重用别名; 经常解决这个问题,使用CTE; 或者将查询包装为子查询,以便可以引用别名.但是,如果在select本身的子查询中引用别名,mySQL似乎允许这样的情况; 所以它在技术上并不是同一水平.
SELECT CONCAT(a, b) AS c1, CONCAT((SELECT c1), 2)
FROM (SELECT 'a' a, 'b' b, 'c' c UNION ALL
SELECT '1', '2', '3') t1;
SELECT 1 a, 2 b, (SELECT A+B) c
, concat((SELECT a),(SELECT b)) d
, greatest((SELECT a),(SELECT b), (SELECT c))
Run Code Online (Sandbox Code Playgroud)
以上两个查询都有效..是的; 他们工作.(或者做得非常好,让它看起来像是有效的)
虽然这不是:正如人们所期望的那样.
SELECT CONCAT(a, b) AS c1, CONCAT(c1, 2)
FROM (SELECT 'a' a, 'b' b, 'c' c UNION ALL
SELECT '1', '2', '3') t1;
Run Code Online (Sandbox Code Playgroud)
所以这里的问题有两个方面:
这是一个缺少文档的mySQL"功能"还是有人可以解释编译器如何解析别名?
这是一个可以依赖的记录功能; 如果是这样,那么在哪里可以了解使用这种方法的含义?
这个问题源于一个已经问过的问题:在MySQL中按别名选择列
对我来说,这看起来像是一个解析错误(在其他数据库中,您会在前两个查询中收到错误)。
我能猜到发生了什么。MySQL 正在解析子查询(select c1)。它在子查询中找不到c1,因此它开始在外部查询中查找引用。
根据 SQL 规则,它应该只查看子句中的列from。然而,MySQL 似乎也在关注列别名。
虽然我认为这是一个 bug,但 MySQL 似乎认为它是一个特性。(这是 MySQL 将“bug”视为“功能”的另一个例子。)考虑以下查询:
SELECT CONCAT((SELECT c1), 2), CONCAT(a, b) AS c1
FROM (SELECT 'a' a, 'b' b, 'c' c UNION ALL
SELECT '1', '2', '3') t1;
Run Code Online (Sandbox Code Playgroud)
以及它生成的错误:
不支持引用“c1”(项目列表中的前向引用)
该错误表明 MySQL 有意解析“向后”引用。
根据记录,我永远不会依赖此功能。它不仅违反了 ANSI 标准,而且是数据库之间的独特行为。这很令人困惑。考虑这个小修改:
SELECT CONCAT(a, b) AS c1, CONCAT((SELECT c1), 2)
FROM (SELECT 'a' a, 'b' b, 'c' c UNION ALL
SELECT '1', '2', '3') t1 CROSS JOIN
(SELECT 'abcdef' as c1) x;
Run Code Online (Sandbox Code Playgroud)
c1查询解析为哪个?我会让你弄清楚这一点。这甚至没有考虑到c1可能是一个变量。