MySQL @rownum:= @ rownum + 1

时间:2018-01-09 05:46:23

标签: mysql

SET @rownum := -1;

SELECT
   round(AVG(t.LAT_N),4)
FROM
(
   SELECT
      @rownum := @rownum + 1 AS rownum,
      STATION.LAT_N AS LAT_N
   FROM
      STATION
   ORDER BY STATION.LAT_N
) AS t
WHERE
   t.rownum IN (
      CEIL(@rownum/2),
      FLOOR(@rownum/2)
   )
;

在上面的代码中,

  1. @rownum:= @ rownum + 1是如何工作的?
  2. 就像在Python中写一些东西:i = i + 1

    在i的值的for循环上下文中有意义,但上面的SQL代码中的for循环在哪里(select执行for循环?)?

    1. 此外,在WHERE子句中,@ rownum被用作表示表中最大行的变量,而在SELECT中,它被用作表示当前行的单个行号的变量被迭代。为什么呢?

    2. 据我了解,@ runum声明了一个持久存入WHERE子句的实例变量。那么做“AS rownum”有什么意义呢?

3 个答案:

答案 0 :(得分:1)

此查询使用行号会话变量来计算表中的LAT_N中值。考虑一个简单的场景,其中LAT_N值的范围是1到10.然后,在分配行号(基于零)之后,我们将得到以下中间表:

LAT_N | rownum
1     | 0
2     | 1
3     | 2
4     | 3
5     | 4
6     | 5
7     | 6
8     | 7
9     | 8
10    | 9

在迭代内部子查询的最后,从@rownum开始的-1的值为9。外部查询如下所示:

SELECT ROUND(AVG(t.LAT_N), 4)
FROM
(the above table) t
WHERE
    t.rownum IN (CEIL(@rownum/2), FLOOR(@rownum/2));

因此,这取了LAT_N的平均值,其中生成的行号为45。这将产生中值5.5。请注意,对于奇数个记录,天花板和楼层都会产生相同的数字,并且只有一个真正的中间值。

Demo

答案 1 :(得分:0)

是的,这个@rownum只使用一个动态变量作为列值,只有当你指定一个别名并在 HAVING 子句中测试它时,它才可以用作行索引。改为使用子查询。

select没有循环,指针会分配给数据中跟踪的每一行,而@rownum运算符已将:=分配给上一个值。

您的查询可能是这样的,其中条件可能会有所不同,但方法是完全概念化的。如果您指定别名或子查询,则可以将其用作行索引。

  

注意:那里,在第二个条件下你不能使用@rownum   条件为false,因为它包含最后一个if中的特定值   任何条件不匹配,那么它将不返回任何数据,但如果你的   条件为真然后您可以使用它。

答案 2 :(得分:0)

  • @rownum:=@rownum+1完全像i = i + 1一样工作。
  • AS rownum正在为此字段添加别名(另请参阅:alias syntax)。您可以为任何字段或表创建别名。

实际上,SQL语句中有两个select个查询。

SELECT @rownum := @rownum + 1 AS rownum, STATION.LAT_N AS LAT_N FROM STATION ORDER BY STATION.LAT_N

这是一个所谓的子查询,其结果将被视为主查询检索信息的表。

对于子查询,您没有给出WHERE子句,因此它将在STATION表中逐行检索每个记录。由于您将@rownum := @rownum + 1 AS rownum写为第一个结果列,因此每行@rownum将增加1。所以,它只是像for循环一样工作。

在这种情况下,子查询将始终在主查询之前运行。因此,在主查询的WHERE子句中,@rownum已经等于STATION表的行数。