关于如何使用MySQL对组内行进行编号有几篇好文章,但实际代码如何工作?我不清楚MySQL在下面的代码中首先评估的内容。
例如,在@yearqt := yearqt as bloc
调用之前放置IF()
会产生不同的结果,而且我不清楚s1
子查询在初始化@
变量时的作用:当MySQL在数据行中运行时,它们何时更新? order by
语句是否在select
之前运行?
以下代码为每个yearqt
组选择三个随机记录。可能有其他方法可以做到这一点,但问题涉及代码如何工作,而不是我如何能够以不同的方式做到这一点,或者我是否可以更有效地做到这一点。谢谢。
select * from (
select customer_id , yearqt , a ,
IF(@yearqt = yearqt , @rownum := @rownum + 1 , @rownum := 1) as rownum ,
@yearqt := yearqt as bloc
from
( select customer_id , yearqt , rand(123) as a from tbl
order by rand(123)
) a join ( select @rownum := 0 , @yearqt := '' ) s1
order by yearqt
) s2
where rownum <= 3
order by bloc
答案 0 :(得分:0)
此问题与引擎检索SQL SELECT
查询结果的方式有关。订单大致如下:
FROM
/ JOIN
阶段)WHERE
条款GROUP BY
/ HAVING
条款ORDER BY
条款因此,关于变量,您现在理解为什么有子查询来初始化它们。此子查询仅在过程开始时评估一次。
之后,项目阶段似乎按照您决定的顺序处理每个选定的属性,这就是为什么放置@yearqt := yearqt as bloc
一个属性会改变下一个/上一个IF
语句的结果的原因。由于每行将被投影一次,这意味着您对变量所做的任何工作都将完成与最终结果集中的行数相同的次数。
答案 1 :(得分:0)
此目的
join ( select @rownum := 0 , @yearqt := '' ) s1
是在语句执行开始时初始化用户定义的变量。因为这是外部查询的行源(MySQL称之为派生表),所以这将在外部查询运行之前执行。我们对这个查询返回的内容并不感兴趣,只是因为JOIN操作它会返回一行。
因此,可以从查询中省略此内联视图s1,并将其替换为在查询之前立即执行的几个SET语句:
SET @rownum := 0;
SET @yearqt := 0;
但是接下来我们要运行三个单独的语句,如果这些语句没有运行,我们会从查询中获得不同的输出,如果这些变量设置为其他值。通过在查询本身中包含它,它是一个单独的语句,我们删除对单独的SET语句的依赖。
这是真正开展工作的查询,仅限于在这种情况下重要的两个表达式
SELEECT IF(@yearqt = t.yearqt , @rownum := @rownum + 1 , @rownum := 1) as rownum
, @yearqt := t.yearqt as bloc
FROM ( ... ) t
ORDER BY t.yearqt
使这个“工作”的一些关键点
MySQL按照它们在SELECT列表中出现的顺序处理SELECT列表中的表达式。
MySQL按照ORDER BY中指定的顺序处理行。
对每行计算对用户定义变量的引用,而不是在语句的开头计算一次。
请注意,MySQL参考手册指出此行为不保证。 (因此,它可能会在将来的版本中发生变化。)
因此,对此的处理可以描述为
表示第一个表达式:
yearqt
列的值与@yearqt用户定义变量的当前值进行比较表示第二个表达式:
净效果是,对于每个处理的行,我们将yearqt列中的值与“之前”处理的行中的值进行比较,我们将保存当前值以与下一行进行比较。< / p>