MySQL @variables 就像做一个设置变量的内联程序,比较然后使用结果作为下一行比较的基础......让我重新格式化您的查询以获得更好的跟踪/可读性。
SELECT
driver,
SUM(`position`)
FROM
( SELECT
driver,
race,
season,
`position`,
IF( @lastDriver = ( @lastDriver := driver),
@auto := @auto + 1,
@auto := 1) indx
FROM
results,
(SELECT @lastDriver := 0,
@auto := 1) A
ORDER BY
driver,
`position`) AS A
WHERE
indx <= 5
GROUP BY
driver ;
内部“From”子句启动查询。Select @ 就像你有一个程序一样..
set @auto = 1
set @lastDriver = 0
准备变量。
因为您有一个 order by 子句,所以查询将从“结果”表中获取记录并将它们按顺序排列。这就像一个待处理的记录队列。现在,考虑通过 do/while 循环运行所有记录的查询。请记住,您的 @auto = 1 和 @lastDriver = 0 开始。
现在,查询将按顺序处理记录,并且一次一个字段就像查询说...
Add the driver to the result
add the race to the result
add the season to the result
add the `position` to the result
现在,您可能正在等待什么...... IF() 和 @ 变量发生了什么。IF() 如下所示
IF( some condition )
add this value to the result
else
add this value to the result
在这种情况下,@lastDriver = (@lastDriver := driver) 是伪的,例如..
set HoldLastDriver = @lastDriver
set @lastDriver = the driver of the current record being processed
if( HoldLastDriver = new value of @lastDriver -- current record driver )
set the auto value = auto value +1
else
set the auto value back to 1 because the driver just changed
其结果被放入“indx”列。
所以,现在,当它到达下一行时,@lastDriver 和 @auto 已经更新并从那里继续......所以,如果你有以下数据,列表将显示值可能只是显示driver 和 auto 列,因为这是查询的关键元素。
BEFORE ROW PROCESSED AFTER ROW PROCESSED
driver pos/race/season @lastDriver @auto @lastDriver @auto
1 3 / A / A 0 1 1 1
1 3 / B / A 1 1 1 2
1 4 / D / B 1 2 1 3
1 5 / E / D 1 3 1 4
1 7 / F / D 1 4 1 5
1 7 / G / D 1 5 1 6
2 2 / A / A 1 6 2 1
2 2 / B / A 2 1 2 2
3 1 / A / A 2 2 3 1
3 2 / B / A 3 1 3 2
3 2 / D / B 3 2 3 3
3 2 / E / D 3 3 3 4
3 3 / F / D 3 4 3 5
3 3 / G / D 3 5 3 6
要结束查询,现在所有这些记录都已处理,您的外部查询将处理驱动程序和 sum(),但仅适用于“indx”(@auto 的 AFTER 版本)小于或等于 5 的记录...因此,@auto 为 6 的两条记录(驱动程序 1 和 3)不会在结果总和中考虑。