回答

收藏

在MySQL中按别名选择列

技术问答 技术问答 78 人阅读 | 0 人回复 | 2023-09-13

我想了解MySQL中的某些特定行为。运行“ select @@ version”,我看到我的版本是5.6.34-log。4 o( M9 B" V$ s. ~5 A5 l
让我使用生成的表放置样本,以使其更易于重现:2 V, j: a; b! F$ W5 X
SELECT
2 s% P4 G* ?2 b5 P: R    CONCAT(a, b) AS 'c1', CONCAT((SELECT c1), 2)
4 X/ H" W' w( L" m8 ?( ^% uFROM
* _0 f7 z6 f; b1 x1 V& s7 g. T    (SELECT 'a', 'b', 'c' UNION ALL SELECT 1, 2, 3) t1;3 H5 x+ U* N$ s% S0 [
正如标题所建议的那样,我最初搜索的是如何通过别名选择列,以便重用计算所得的字段,从而避免了冗长的查询。如文档中所述,大多数答案要么建议使用子查询,要么使用变量-
/ b5 N* b" \) U, a8 ]- J8 {- ^9 @一种可读性差,而另一种则不能由自己的数据库开发人员来保证。然后,我从这个答案中学到了这种方法,并且不太了解它-" a7 X( U/ E/ i( ^) B/ I5 U' o! o
的确,我什至不知道该如何称呼这种操作/条款。) u% m: q6 ?9 H( Z8 t+ l! [
至少在此MySQL版本中,它似乎工作得很好。唯一的例外是涉及包含聚合函数的列(如下所示)-它会引发1247(错误引用)错误,并且感觉很合理。/ i/ n* v/ l' M
-- THIS DOESN'T WORK!
' h' s+ B3 ^# G# y5 JSELECT
( E- b% h2 O' }5 {" b( e; ?    CONCAT(a, b) AS c1, CONCAT((SELECT c1), 2) as c2
. j: E7 |! O  V+ S. PFROM) v5 |8 s( f* \: H+ q7 E; w
    (SELECT 'a' as a, 'b' as b, 'c' as c UNION ALL SELECT '1', 2, 3) t1;
1 h1 Q8 d! o3 i5 e6 C6 \, o我已经阅读了有关该主题的许多答案,但这是对此类操作的唯一参考,并且由于我不知道其名称,因此无法对其进行更深入的研究。有谁知道该结构的名称,我如何更好地理解它?! J" d$ D- _- F0 Q" s8 `4 M
编辑:我不试图执行在不工作查询中显示的操作。确实,我正在尝试了解MySQL的行为。已经存在的问题很容易理解如何使用子查询来执行此操作,依此类推-
$ w1 c3 ~, @; }* }% t, h& C2 M0 e并不是重点。我的主要问题是了解MySQL在其中执行哪种操作以及如何调用该操作,因为我从未读过类似的东西(这将是带有自动选择的查询吗?)
, [3 E; T' N/ U2 Z% Y. m( M" ~编辑2:这篇文章激发了有关此MySQL行为的更具体,更好的书面问题,可以在此处找到。4 _5 f/ m, [; B0 ?' ^( ~
                : d  T8 P) t) I" d
解决方案:
9 p$ M+ W# x9 J* E2 J! N' [% _3 A5 j                / w. |% J, s6 B- n! R. j3 O: K5 Z
8 a( A1 ~5 X# u+ [8 V5 N5 m
  @. T& ^& n* h: ]2 U9 V
                简短答案:
5 ~4 g4 I) k7 K# r3 H+ \. f[ol]SELECT列表中对别名的引用或 ) [+ s1 v: v, n" V% D# r
别名表达1 e9 i; l9 |# q, Z: J2 d
[/ol]
. o. n  b6 T: B7 o2 Z+ w* U到目前为止,我发现的唯一文档是:https :, M' {) Z& L: e2 T
//bugs.mysql.com/bug.php?id=79549  i: ?, ]) O0 M# _+ \( r
在该链接中有以下内容:
6 r: p  H9 B2 ^6 G$ e[2015年12月9日15:35] Roy Lyseng …这是原始决定的较长背景:
1 B! @* i0 r7 j7 a. L# E2 n与在WHERE子句(和GROUP BY)中子查询中对别名的引用相反, % H9 R+ O/ W( Y$ R. e* [
没有理由(除标准合规性之外)我们不应该在SELECT列表中允许对别名的引用
,因为它们应该 在SELECT列表
& Q" c& ]; M2 H* A2 v* W6 g中可用。查询执行的同一阶段。但是5.6中的支持相当随意:2 H, u1 P* v0 k- U: e
鉴于此:创建表t1(a int,b int)," g# n' x! A6 n) h6 E
SELECT列表中的别名无效:2 G+ }8 F% d# s% ~
  select a+b as c,c+1 from t1;- g; B- J! J4 [( }' ?4 b/ M  p! Q

# c3 E0 j# u  M7 q, o错误1054(42S22):“字段列表”中的未知列“ c”& W9 D9 x7 b( r4 w8 c( A, A5 `+ X
  s6 P! W1 _) U& n' Z
但是在子查询中,对c的引用是有效的:
' ]& p2 ?' ~  j4 g) b4 E# n: `  select a+b as c,(select c+1) from t1;) c0 `9 {6 Q9 A3 }
并且子查询必须在别名定义之后:
& S+ j0 m' R9 D4 z, r/ ?  select (select c+1),a+b as c from t1;8 T, n4 V: n- c# N; k, g9 a- k

7 q7 z' E+ J4 D  ?, G错误1247(42S22):不支持参考“ c”(项目列表中的前向参考)
" ^" h" g! K$ S9 k( k- |6 U( w% W) X6 A
因此,很容易说 在SELECT列表中对别名的引用的
- G: k" D# ]2 s支持是非常特殊的。尽管如此,我们将尝试重新实现旧的解决方案,但没有尝试清除此功能支持中的明显漏洞。但是,不会在WHERE子句中的子查询中引用别名。
3 b6 G- T/ c* |除了在标准文档中描述此功能的错误报告之外,我还一直在寻找文档。但到目前为止没有运气。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则