回答

收藏

在MySQL中按别名选择列

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

我想了解MySQL中的某些特定行为。运行“ select @@ version”,我看到我的版本是5.6.34-log。
, M" [4 L; B3 {. M- M5 ~; p/ j让我使用生成的表放置样本,以使其更易于重现:* P: e& i) V4 Q" C! ]) Q
SELECT
3 |! x5 f& s$ O6 R. B- Q  O7 p    CONCAT(a, b) AS 'c1', CONCAT((SELECT c1), 2)5 B! Q7 w$ l; i( b
FROM
6 k" |, |( L/ ~, A/ l5 {    (SELECT 'a', 'b', 'c' UNION ALL SELECT 1, 2, 3) t1;5 F' l- U( f  u- i# O& z
正如标题所建议的那样,我最初搜索的是如何通过别名选择列,以便重用计算所得的字段,从而避免了冗长的查询。如文档中所述,大多数答案要么建议使用子查询,要么使用变量-
1 S# ]# Y6 f9 a' }1 f$ S一种可读性差,而另一种则不能由自己的数据库开发人员来保证。然后,我从这个答案中学到了这种方法,并且不太了解它-
. r% `; C* n* W. `- j- ?: l. e7 U的确,我什至不知道该如何称呼这种操作/条款。% k/ a6 j5 K6 Z  J- ^6 U
至少在此MySQL版本中,它似乎工作得很好。唯一的例外是涉及包含聚合函数的列(如下所示)-它会引发1247(错误引用)错误,并且感觉很合理。$ i% k8 |3 F4 _% L/ O% `
-- THIS DOESN'T WORK!
5 G% b8 b0 M; Z0 u% U. QSELECT . R( s; C1 Q8 W, R9 v
    CONCAT(a, b) AS c1, CONCAT((SELECT c1), 2) as c2$ c5 y9 B1 G, a  {  p% R
FROM
: z/ ]2 ]% T, T, K8 W    (SELECT 'a' as a, 'b' as b, 'c' as c UNION ALL SELECT '1', 2, 3) t1;3 T; o) W0 f! l6 ]0 J
我已经阅读了有关该主题的许多答案,但这是对此类操作的唯一参考,并且由于我不知道其名称,因此无法对其进行更深入的研究。有谁知道该结构的名称,我如何更好地理解它?
/ `7 C% P, |4 J  X编辑:我不试图执行在不工作查询中显示的操作。确实,我正在尝试了解MySQL的行为。已经存在的问题很容易理解如何使用子查询来执行此操作,依此类推-
; a& B& U' A2 P& T  J并不是重点。我的主要问题是了解MySQL在其中执行哪种操作以及如何调用该操作,因为我从未读过类似的东西(这将是带有自动选择的查询吗?). m& F9 Y/ _6 `# o. s
编辑2:这篇文章激发了有关此MySQL行为的更具体,更好的书面问题,可以在此处找到。4 l! T6 p( _7 C, n: c0 K3 |) J
                4 R5 @, f1 g0 v1 l% F
解决方案:
1 D5 F7 p) S+ n9 e! ?               
9 x* H. H. w' ?, N  p$ e5 O) T. k! G7 h3 L

( h: Q- U; Y5 i- e                简短答案:
% v8 Q) z9 Q) C" k[ol]SELECT列表中对别名的引用或
( S: R  \7 C% X; S& K别名表达
' C" l8 a% {$ f+ ^. q7 N( C" V* O[/ol]6 s6 E$ D4 F$ X% \1 l6 z2 T
到目前为止,我发现的唯一文档是:https :+ i8 n( f6 L% D1 x
//bugs.mysql.com/bug.php?id=79549  G5 k& b) y$ F6 Y
在该链接中有以下内容:
- ?% k8 X& I( j/ V. F( O[2015年12月9日15:35] Roy Lyseng …这是原始决定的较长背景:& E+ Q* R5 e7 p7 ^. q: s0 ^4 c7 e
与在WHERE子句(和GROUP BY)中子查询中对别名的引用相反, " z6 _( g7 m7 W1 ^
没有理由(除标准合规性之外)我们不应该在SELECT列表中允许对别名的引用
,因为它们应该 在SELECT列表
7 C3 l0 T8 A" S& v0 b中可用。查询执行的同一阶段。但是5.6中的支持相当随意:
" |7 H; a+ S3 k; k: {# L7 m' u鉴于此:创建表t1(a int,b int),+ W1 o0 X/ J- N( L
SELECT列表中的别名无效:
- B0 x/ l& L$ p( o! Q  select a+b as c,c+1 from t1;( f  B8 k! {8 s8 v5 o7 F# E+ u

/ \& n# u& |1 m: W; d错误1054(42S22):“字段列表”中的未知列“ c”
# `4 Q/ q3 q" Q6 V9 J- h
2 ^# L2 [! u4 E% A3 }) A但是在子查询中,对c的引用是有效的:
' ?- u9 ?# B# s" Q) Z3 R% ~9 ]) n  select a+b as c,(select c+1) from t1;5 M: q* b2 W1 }/ @
并且子查询必须在别名定义之后:
& [' c7 G9 z! X8 P- Y  select (select c+1),a+b as c from t1;
) t" I. w0 y; U* j7 Y" L* x5 ?& R$ T* F3 c+ \# e
错误1247(42S22):不支持参考“ c”(项目列表中的前向参考)# x& Q8 _' B8 z, }
+ A/ v2 j& a+ H5 {1 K( {) `
因此,很容易说 在SELECT列表中对别名的引用的5 D, b3 C" i$ e/ o1 C
支持是非常特殊的。尽管如此,我们将尝试重新实现旧的解决方案,但没有尝试清除此功能支持中的明显漏洞。但是,不会在WHERE子句中的子查询中引用别名。& G  M0 a. U- o3 \) ?
除了在标准文档中描述此功能的错误报告之外,我还一直在寻找文档。但到目前为止没有运气。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则