在子查询中使用初始化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
窗口(分析)函数