老板的第一个问题:昨天卖了多少

老板在工位后面喊:「昨天有多少单?」--你人生第一条业务查询。

学 40 min
练 65 min
盘 15 min
共 120 分钟

学 · 40 min

  1. 01SELECT 的解剖:选哪些列、从哪张表、* 与具体列

    场景老板问昨天卖了多少。第一条 SQL 之前,先把 SQL 的「主谓宾」拆清楚。

    select 列 决定输出什么,from 表 决定从哪拿。* 是全部列,探索数据时用它看长相;正式查询写具体列--少传无用数据,读 SQL 的人一眼看出结果长什么样。

    -- 探索:先看看数据长什么样
    select * from orders limit 10;
    
    -- 正式:要什么写什么
    select id, total_amount, created_at from orders limit 10;

    易错生产代码里 select * 配上表结构变更会悄悄多传/错传数据,报错都懒得报。

  2. 02WHERE 比较运算符与日期字面量

    场景5 万行订单,老板只要昨天的。全表看一遍是人的活,不是 SQL 的。

    where 逐行判断表达式,结果为 TRUE 的行才保留。日期写法用「左闭右开」区间:>= 昨天 0 点< 今天 0 点,一秒不多不少。不硬编码日期用 current_date - 1

    select count(*)
    from orders
    where created_at >= current_date - 1   -- 昨天 0 点起
      and created_at <  current_date;      -- 今天 0 点止

    易错时间戳别用等值判断:created_at = current_date - 1 只匹配「昨天 0 点整」那一瞬间。也别写 between(含两头,边界多算一天)。

  3. 03ORDER BY 与 LIMIT:找「最大 / 最新」的标准姿势

    场景老板要看金额最大的 10 单、最新的 10 单。

    标准姿势 = order by 排序键 desc 把想要的行顶到最上面,limit n 截取前 n 行。Top N 问题在 SQL 里永远这么解,没有别的语法。

    select id, total_amount
    from orders
    order by total_amount desc
    limit 10;

    易错金额或时间相同的行,顺序是未定义的--补第二排序键(如 order by total_amount desc, id desc)才稳定,这是面试加分点。

  4. 04排序不稳定:LIMIT 10 不加 ORDER BY 结果每次都不一样

    场景limit 10 连跑 5 次,5 看似随机的结果,以为数据库坏了。

    SQL 标准就不承诺无 ORDER BY 时的返回顺序:物理存储顺序、缓存、并行扫描都会影响先吐出哪 10 行。数据库没坏,是你的查询没定义「前 10」的依据。

    -- 连跑 5 次,对比输出
    select id, total_amount from orders limit 10;
    select id, total_amount from orders limit 10;
    select id, total_amount from orders limit 10;

    易错不带 order by 的 limit = 「随便给我 10 行」,业务上几乎一定是 bug。

练 · 65 min

  1. select * from orders limit 10 先看看数据长什么样
    参考答案

    顺眼扫一遍:哪些列有 NULL、金额长什么样、时间格式--后面几天的题都建立在对长相的印象上。

    select * from orders limit 10;
  2. 查昨天的订单数(先手写日期字面量,再想怎么不硬编码)
    参考答案

    用「左闭右开」范围,别对 created_at 套 ::date 或 date_trunc--列上套函数会让索引失效,第 6 周会亲眼看到。灌数脚本锚定 current_date,两种写法结果一致。

    -- 先手写日期字面量(日期换成你做题时的「昨天」)
    select count(*) from orders
    where created_at >= timestamp '2026-08-27'
      and created_at <  timestamp '2026-08-28';
    
    -- 不硬编码
    select count(*) from orders
    where created_at >= current_date - 1
      and created_at <  current_date;
  3. 查金额 > 1000 的订单数
    参考答案
    select count(*) from orders where total_amount > 1000;
  4. 按金额从大到小取前 10 单;再按 created_at 取最新 10 单
    参考答案

    面试加分点:补第二排序键(如 order by created_at desc, id desc)--金额或时间相同的行顺序未定义,加个 id 才稳定。

    select id, total_amount from orders order by total_amount desc limit 10;
    
    select id, created_at from orders order by created_at desc limit 10;
  5. LIMIT 10 不加 ORDER BY 连跑 5 次,观察差异并解释
    参考答案

    五次结果大概率不同。SQL 不承诺无 ORDER BY 时的顺序,返回顺序取决于物理存储和执行计划;「LIMIT 10 不加 ORDER BY」在业务上等于「随便取 10 行」。

过关标准 不查文档写出「日期范围 + 排序 + 取前 N」的查询。