我想了解MySQL中的某些特定行为。运行"选择@@ version",我看到我的版本是5.6.34-log。
让我使用生成的表格放置样本,以便更容易重现:
SELECT
CONCAT(a, b) AS 'c1', CONCAT((SELECT c1), 2)
FROM
(SELECT 'a', 'b', 'c' UNION ALL SELECT 1, 2, 3) t1;
我最初搜索的是,如标题所示,如何通过别名选择列,以便重用计算字段,避免长查询。大多数答案要么建议使用子查询或变量 - 一个具有较差的可读性,另一个则不是由自己的DB开发人员保证,如documentation中所述。然后,我从这个answer学到了这个方法,并且不太了解它 - 事实上,我甚至不知道如何调用这种操作/子句。
它似乎运行得很好,至少在这个MySQL版本中。唯一的例外是涉及包含聚合函数的列(如下所示) - 它会引发1247(误引用)错误,这感觉非常合理。
-- THIS DOESN'T WORK!
SELECT
CONCAT(a, b) AS c1, CONCAT((SELECT c1), 2) as c2
FROM
(SELECT 'a' as a, 'b' as b, 'c' as c UNION ALL SELECT '1', 2, 3) t1;
我已经阅读了很多关于这个主题的答案,但这是对这种操作的唯一参考,而且,由于我不知道它的名字,我无法深入了解它。有谁知道这个结构如何调用,我怎样才能更好地理解它?
编辑:我没有尝试执行不工作查询中显示的操作。实际上,我试图理解MySQL的行为。已经存在的问题需要了解如何使用子查询来做到这一点,等等 - 这不是重点。我的主要问题是了解MySQL在那里执行什么样的操作以及它是如何调用的,因为我从来没有读过类似的东西(它是一个带有自动选择的查询?)
编辑2:这篇文章激发了关于这种MySQL行为的更具体和更好的书面问题,可以找到here。
答案 0 :(得分:1)
简短回答:
到目前为止,我发现的唯一文档是: https://bugs.mysql.com/bug.php?id=79549
在该链接中有以下内容:
[2015年12月9日15:35] Roy Lyseng ... 以下是原始决定的较长背景:
与WHERE子句中的子查询中的别名(以及GROUP BY中的别名)的引用相反, 没有理由(标准合规除外)我们不应该允许引用别名中的别名SELECT list ,因为它们应该在查询执行的同一阶段可用。但5.6中的支持是相当随意的:
鉴于此:创建表t1(一个int,b int),
SELECT列表中的别名无效:
select a+b as c,c+1 from t1;
ERROR 1054(42S22):“字段列表”中的未知列“c”
但在子查询中,对c的引用是有效的:
select a+b as c,(select c+1) from t1;
子查询必须在定义别名之后:
select (select c+1),a+b as c from t1;
ERROR 1247(42S22):不支持参考'c'(项目列表中的前向参考)
因此,很容易说 对SELECT list 中别名的引用是对ad-hoc的支持。尽管如此,我们将尝试重新实现旧的解决方案,但没有尝试清理支持此功能的明显漏洞。但是,不会重新实现在WHERE子句中的子查询中引用别名。
我还在查找标准文档中描述此功能的错误报告之外的文档;但到目前为止还没有运气。
答案 1 :(得分:0)
为什么不再使用相同的表达式,它不会像重用那样伤害
SELECT
CONCAT(a, b) AS 'c1', CONCAT(CONCAT(a, b), 2)
FROM
(SELECT 'a', 'b', 'c' UNION ALL SELECT 1, 2, 3) t1;
答案 2 :(得分:0)
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;
或者更好的是,如果你有窗口功能(不是你的MySQL版本,而是读者):
// only with MariaDB 10.2 and up
WITH q AS (SELECT 'a' a, 'b' b, 'c' c UNION ALL SELECT 1, 2, 3)
SELECT * FROM q WHERE a='a'