在子查询中使用初始化mysql中的用户定义变量

在子查询中使用初始化mysql中的用户定义变量,mysql,Mysql,我正在仔细阅读这个答案。因为我无法理解下面子查询中的初始化 SELECT @row := @row +1 AS rownum, [column name] FROM ( SELECT @row :=0) r, [table name] 如何准确地初始化 选择@row:=0 他在工作吗 表'r'和'table name'之间是否发生某种连接 如果我将上述查询更改为以下内容,性能是否会有任何差异 设置@row=0 挑选 @行:=@row+1作为rownum,[表名]中的[列名

我正在仔细阅读这个答案。因为我无法理解下面子查询中的初始化

SELECT 
    @row := @row +1 AS rownum, [column name] 
FROM ( 
    SELECT @row :=0) r, [table name]
如何准确地初始化

选择@row:=0

他在工作吗

表'r'和'table name'之间是否发生某种连接

如果我将上述查询更改为以下内容,性能是否会有任何差异

设置@row=0

挑选 @行:=@row+1作为rownum,[表名]中的[列名]


请分享您的想法。

使用两条语句,在单独的语句中初始化用户定义的变量将获得同等的性能

我们可以不使用
SET
语句

SELECT @row : = 0
这将获得相同的结果,为用户定义的变量
@row
赋值。不同之处在于MySQL需要准备一个结果集返回给客户端。我们使用
SET
语句避免了这种情况,该语句不返回resultset

对于两个单独的语句执行,发送额外语句的开销是:解析标记、语法检查、语义检查。。。并将状态返回给客户端。这只是一小部分开销。我们不会一丝不挂地注意到它

因此,性能将相当


我强烈建议放弃join操作的老式逗号语法,改用
join
关键字

考虑以下问题:

SELECT t.foo 
  FROM r 
 CROSS
  JOIN t
 ORDER BY t.foo 
当表
r
保证只包含一行时会发生什么情况

该查询相当于:

SELECT t.foo 
  FROM t
 ORDER BY t.foo
我们可以使用SELECT查询代替表或视图。例如,考虑:

SELECT v.foo 
  FROM ( SELECT t.foo 
           FROM t
       ) v

也考虑这个查询会发生什么:

SELECT @foo := 0
SELECT 'bar'
  FROM ( SELECT @foo := 0 ) r
没有FROM子句(或Oracle风格的
FROM dual
),因此查询将返回一行。将对“选择”列表中的表达式求值。。。常量值0被分配给用户定义的变量@foo

考虑这个查询:

SELECT @foo := 0
SELECT 'bar'
  FROM ( SELECT @foo := 0 ) r
在外部查询运行之前,将执行参数内部的SELECT。(MySQL称之为“派生表”,但更一般地说,它是一个内联视图定义。)其最终效果是将常量0分配给用户定义的变量,并返回一行。因此外部查询返回一行

如果我们了解这一点,我们就有了我们需要了解的东西:

 SELECT t.mycol
   FROM ( SELECT @row := 0 ) r
  CROSS
   JOIN mytable t
  ORDER
     BY t.mycol
计算内联视图
r
,选择返回一行,值
0
分配给用户定义变量
@row
。由于
r
保证返回一行,我们知道带
mytable
的笛卡尔积(交叉连接)将导致
mytable
中的每行返回一行。有效地只生成一份
mytable


要回答未被问到的问题:


在语句中而不是单独的语句中进行初始化的好处是,我们现在有了一个单独的语句。它消除了依赖关系,即不需要单独执行
SET
语句来分配用户定义的变量。它还减少了到数据库的往返,以准备和执行单独的语句。

这是一种基于逗号的旧式隐式连接语法。你应该避免使用它,使用现代的第一种形式的作品是出于偶然,而不是出于设计,它可能会在任何时候停止工作。第二种形式更好,但如果您想要第n行,请升级到MySQL 8+并使用(…)上的
row\u number()
现在,在这个问题中,它是一个没有任何匹配条件的连接。所以基本上,第一个表中的每一行都与第二个表中的每一行(笛卡尔积)连接,这在形式上称为交叉连接。这种交叉连接确保每一行都可以访问初始化的variable@CaiusJard:第一种形式依赖于无法保证的行为;将其描述为“偶然”和“随时可能停止工作”是不恰当的。观察到的行为是可重复的。这是MySQL服务器中代码路径的结果,而不是随机事件的结果。也许您想指出的是MySQL参考手册中的特定警告,即在单个语句中分配和计算用户定义变量时,操作顺序没有任何保证。操作顺序可能出乎意料,但不是“偶然”决定的。@spencer7593好的,这是我考虑过的细节级别,但没有(需要,因为肯定会有其他人来填写)。“在任何时刻”,我指的是随机事件“当DBA升级到MySQL版本X时,此‘功能’在您离开公司很久之后消失,默默地破坏您的代码,可能没有人可以快速修复它”。=>使用经过批准、有文档记录、受支持的功能Spencer,我有一个疑问,如果我使用固定方式,那么我不需要交叉连接,对吗?你应该做得不够吗?设置@row=0;选择/@row:=/@row+1作为rownum,[table name]中的[column name]Added/before@row以避免堆栈溢出警告“您不能引用这么多用户”。我运行了上述查询,它对我有效。我想确保它不会意外地工作删除交叉连接的原因是,我有一个百万行的大表,我发现使用MySQL 8.0“set@row=0”版本的执行时间更短(并且早期版本不需要向后兼容),我更喜欢使用
row\u NUMBER
窗口(分析)函数