mysql - 在子查询中初始化 mysql 中的用户定义变量
问题描述
我正在阅读这个答案 How do you select every n-th row from mysql。因为我无法理解以下子查询中的初始化。
SELECT
@row := @row +1 AS rownum, [column name]
FROM (
SELECT @row :=0) r, [table name]
究竟是如何初始化的
选择 @row :=0
正在工作中?
表“r”和“表名”之间是否发生某种连接?
如果我将上述查询更改如下,性能会有什么不同吗?
设置@row = 0;
SELECT @row := @row +1 AS rownum, [列名] FROM [表名]
请分享你的想法。
解决方案
使用两个语句,在单独的语句中初始化用户定义的变量将是等效的性能。
代替SET
声明,我们可以做
SELECT @row : = 0
这将达到相同的结果,为用户定义的变量赋值@row
。不同之处在于 MySQL 需要准备一个结果集以返回给客户端。SET
我们使用不返回结果集的语句来避免这种情况。
对于两个单独的语句执行,发送额外语句会产生开销:解析标记、语法检查、语义检查……并将状态返回给客户端。这是少量的开销。我们不会注意到它onesie-twosie。
所以性能将是相同的。
我强烈建议放弃用于连接操作的老式逗号语法,而改用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
没有 FROM 子句(或 Oracle 样式FROM dual
),因此查询将返回单行。SELECT 列表中的表达式被求值...常量值 0 被分配给用户定义的变量 @foo。
考虑这个查询:
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
,SELECT 返回单行,将值0
分配给用户定义的变量@row
。由于r
保证返回单行,我们知道笛卡尔积(交叉连接)mytable
将导致mytable
. 有效地只产生mytable
.
要回答未提出的问题:
在语句中进行初始化而不是单独的语句的好处是我们现在有一个独立的语句。它消除了依赖关系,即不需要单独执行SET
语句来分配用户定义的变量。这也减少了到数据库的往返以准备和执行单独的语句。
推荐阅读
- bash - 将 curl 响应的特定部分保存到变量
- typescript - NestJS IoC 和第 3 方依赖项
- python - 通过 pandas 变换使用多个函数
- javascript - 角度返回 ZoneAwarePromise 而不是 String
- xamarin.android - Azure 服务总线和 Xamarin.Android MessageHandler
- python - 以df为输入的python应用函数
- php - 如何在数组中创建循环
- python - 使用 ExcelWriter 时如何允许重复的工作表名称?
- swift - 为不当内容实施“报告”功能 swift firebase
- python - pip install 时可以选择排除一些依赖项