简体   繁体   English

在 MySQL 中按别名选择列

[英]Select column by alias in MySQL

I would like to understand certain specific behavior in MySQL.我想了解 MySQL 中的某些特定行为。 Running "select @@version", I see my version is 5.6.34-log.运行“select @@version”,我看到我的版本是 5.6.34-log。

Let me put the sample, using a generated table in order to make it easier to reproduce:让我把示例放在一个生成的表中,以便更容易重现:

SELECT 
    CONCAT(a, b) AS 'c1', CONCAT((SELECT c1), 2)
FROM
    (SELECT 'a', 'b', 'c' UNION ALL SELECT 1, 2, 3) t1;

What I was searching for initially was, as suggested by the title, how to select a column by its alias, in order to reuse calculated fields, avoiding long queries.正如标题所暗示的那样,我最初搜索的是如何通过别名选择列,以便重用计算字段,避免长查询。 Most of the answers either suggest using subqueries or variables - one has poor readability, and the other is not assured by the very own DB devs, as stated in documentation .大多数答案要么建议使用子查询,要么建议使用变量——一个可读性差,另一个没有得到自己的数据库开发人员的保证,如文档中所述 Then, I learned this method from this answer , and can't quite understand it - indeed, I don't even know how to call this kind of operation/clause.然后,我从这个答案中学到了这个方法,并不能完全理解它 - 事实上,我什至不知道如何调用这种操作/子句。

It seems to work very well, at least in this MySQL version.它似乎工作得很好,至少在这个 MySQL 版本中。 The only exception is when it comes to columns which contains aggregate functions (shown below) - it throws a 1247 (misreference) error, and that feels quite reasonable.唯一的例外是当涉及包含聚合函数的列时(如下所示)——它会抛出 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;

I've read many answers around this theme, but that is the only reference to this kind of operation, and, since I don't know its name, I can't look deeper into it.我已经阅读了很多关于这个主题的答案,但这是对这种操作的唯一参考,而且由于我不知道它的名字,我无法深入研究它。 Does anyone know how is this structure called, how can I understand it better?有谁知道这个结构是如何命名的,我怎样才能更好地理解它?

EDIT: I'm not trying to perform that operation shown in the not working query.编辑:我没有尝试执行不工作查询中显示的操作。 Indeed, I'm trying to understand MySQL behavior.确实,我正在尝试了解 MySQL 的行为。 The already existing questions are enoug to understand how to do that using a subquery, and so on - that is not the point.已经存在的问题足以了解如何使用子查询来做到这一点,等等 - 这不是重点。 My main issue is to understand what kind of operation is MySQL performing there and how is it called, since I've never read anything about something like that (would it be a query with an auto select?)我的主要问题是了解 MySQL 在那里执行什么样的操作以及它是如何调用的,因为我从来没有读过任何类似的东西(它会是一个带有自动选择的查询吗?)

EDIT 2: This post has inspired a more specific and better written question about this MySQL behavior, which can be found here .编辑 2:这篇文章激发了一个关于这个 MySQL 行为的更具体和更好的书面问题,可以在这里找到。

Short answer:简短的回答:

  1. references to aliases in SELECT list or对 SELECT 列表中的别名的引用或
  2. Aliased expressions别名表达式

The only documentation I've found on this so far has been: https://bugs.mysql.com/bug.php?id=79549到目前为止,我在这方面找到的唯一文档是: https : //bugs.mysql.com/bug.php?id=79549

In that link there is the following:在该链接中有以下内容:

[9 Dec 2015 15:35] Roy Lyseng ... Here is a longer background for the original decision: [2015 年 12 月 9 日 15:35] Roy Lyseng ... 以下是原始决定的较长背景:

Contrary to references to aliases in subqueries in the WHERE clause (and in GROUP BY, for that matter), there is no reason (except standard compliance) that we should not allow references to aliases in the SELECT list , since they should be available in the same phase of query execution.与 WHERE 子句(以及 GROUP BY,就此而言)子查询中对别名的引用相反,我们没有理由(除了符合标准)不允许在 SELECT 列表中引用别名,因为它们应该在查询执行的同一阶段。 But the support in 5.6 was quite arbitrary:但是 5.6 中的支持非常随意:

Given this: create table t1(a int, b int),鉴于此:创建表 t1(a int, b int),

Alias in SELECT list is not valid: SELECT 列表中的别名无效:

  select a+b as c,c+1 from t1;

ERROR 1054 (42S22): Unknown column 'c' in 'field list'错误 1054 (42S22):“字段列表”中的“c”列未知

But within a subquery, reference to c is valid:但是在子查询中,对 c 的引用是有效的:

  select a+b as c,(select c+1) from t1;

And subquery must be after definition of alias:并且子查询必须在别名定义之后:

  select (select c+1),a+b as c from t1;

ERROR 1247 (42S22): Reference 'c' not supported (forward reference in item list)错误 1247 (42S22):不支持引用“c”(项目列表中的前向引用)

So, it is easy to say that support for references to aliases in SELECT list was rather ad-hoc.因此,很容易说对SELECT 列表别名的引用的支持是临时的。 Nevertheless, we will try to reimplement the old solution, but with no attempt at cleaning up the obvious holes in the support for this feature.尽管如此,我们还是会尝试重新实现旧的解决方案,但不会尝试清理支持此功能的明显漏洞。 But referencing aliases in subqueries in the WHERE clause will not be reimplemented.但是不会重新实现在 WHERE 子句中的子查询中引用别名。

I'm yet looking for documentation beyond the bug report describing this functionality in the standard documents;我还在寻找标准文档中描述此功能的错误报告之外的文档; but thus far no luck.但到目前为止还没有运气。

Why not use the same expression again, it wont hurt Reuse much like为什么不再次使用相同的表达式,它不会像Reuse一样伤害Reuse

SELECT 
    CONCAT(a, b) AS 'c1', CONCAT(CONCAT(a, b), 2)
FROM
    (SELECT 'a', 'b', 'c' UNION ALL SELECT 1, 2, 3) t1;
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;

Or better, if you have window functions (not on your version of MySQL, but for readers):或者更好,如果您有窗口函数(不是在您的 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'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM