mysql 书学顺序和查询顺序

这里涉及SQL语句的语法顺序和执行顺序了,我们常见的SQL语法顺序如下:

SELECT DISTINCT <Top Num> <select list>

FROM [left_table] <join_type>

JOIN <right_table> ON <join_condition>

WHERE <where_condition>

GROUP BY <group_by_list>

WITH <CUBE | RollUP>

HAVING <having_condition>

ORDER BY <order_by_list>

数据库引擎在执行SQL语句并不是从SELECT开始执行,而是从FROM开始,具体执行顺序如下(关键字前面的数字代表SQL执行的顺序步骤):

(8)SELECT (9)DISTINCT (11)<Top Num> <select list>

(1)FROM [left_table]

(3)<join_type> JOIN <right_table>

(2) ON <join_condition>

(4)WHERE <where_condition>

(5)GROUP BY <group_by_list>

(6)WITH <CUBE | RollUP>

(7)HAVING <having_condition>

(10)ORDER BY <order_by_list>

从上面可以看到SELECT在HAVING后才开始执行,这个时候SELECT后面列的别名只对后续的步骤生效,而对SELECT前面的步骤是无效的。所以如果你在WHERE,GROUP BY,或HAVING后面使用列的别名均会报错。

不少地方说的顺序和这个不太一致:主要是select 和 order的关系,谁先谁后的问题

本人亲自实验:先order by 再 select。

SELECT *
FROM (
  SELECT *,
         IF(@prev_space_id = space_id, @row_number := @row_number + 1, @row_number := 1) as row_number,
         @prev_space_id := space_id
  FROM badges, (SELECT @prev_space_id := NULL, @row_number := 0) as vars
  ORDER BY space_id, created_at DESC
) as t
WHERE row_number <= 4;

以上代码是先按照space_id, created_at分组。然后每组按顺序设置row_number。

详解:

  这个查询语句使用了 MySQL 中的变量和子查询来模拟 ROW_NUMBER() 窗口函数的功能。让我们逐步解释它的执行过程:

  1. 首先,它创建了一个名为 vars 的子查询,并定义了两个变量 @prev_space_id@row_number,并将它们都初始化为 0。这个子查询只会执行一次,并在后续查询中使用这两个变量。

     
    (SELECT @prev_space_id := NULL, @row_number := 0) as vars
    ```
  2. 然后,它从 badges 表中选择所有列,并将其与 vars 子查询进行交叉连接。这个查询会将 badges 表中的每一行都复制一遍,并将 @prev_space_id@row_number 变量的值初始化为 0。

    less
    FROM badges, (SELECT @prev_space_id := NULL, @row_number := 0) as vars
    ```
  3. 接下来,它使用 IF 函数和变量来为每个 space_id 分配一个行号 row_number。对于每个徽章,如果其 space_id 等于上一行的 space_id,则将 @row_number 的值加 1,并将该值作为 row_number 的值;否则,将 @row_number 重置为 1,并将其作为 row_number 的值。同时,将当前 space_id 的值保存到 @prev_space_id 变量中,以便下一行使用。

    less
    IF(@prev_space_id = space_id, @row_number := @row_number + 1, @row_number := 1) as row_number,
    @prev_space_id := space_id
    ```
  4. 最后,它将所有列和计算出的 row_number 值作为结果集返回。这个查询不会过滤或排序结果,只是为每个徽章分配了一个行号。

     
    SELECT *, IF(...), ...
    ```

你可以将这个查询语句作为子查询,然后在外部查询中选择每个 space_id 下行号最小的4个徽章,以获取你想要的结果集。

posted @ 2023-07-30 00:12  若-飞  阅读(24)  评论(0编辑  收藏  举报