语句 · 2026 年 6 月 7 日 · 9 分钟
NULL 不是 0,也不是空字符串
NULL 参与比较得到未知,未知在 WHERE 里被丢掉。于是「状态不等于取消」不会包含状态为空的行。问数里这是静默错误:数偏了,语句还显得正确。抽样时专门看空,就是为了这件事。
金额空
SUM 忽略空,AVG 的分母不含空。要不要把空当 0,必须写在口径里。
状态空
空是未回写还是未知。未知能不能进「已支付」,通常不能。
连接空
外连接会产生空。空意味着没连上,不是值为零。
一次完整的问法可以先写成下面这样:
已支付金额把空当 0 计入合计;状态空的订单排除。
落到语句上,草稿常常是:
SELECT SUM(COALESCE(pay_amount, 0)) AS gmv
FROM orders
WHERE pay_time >= DATE '2026-03-01'
AND pay_time < DATE '2026-04-01'
AND pay_status = 'paid';
COALESCE 是口径,不是语法糖。用了就要写在卡片上:空当 0。
语句是收据,默认只读
第一纪律是 SELECT。草稿里出现更新、删除、结构变更,整张收据作废。第二纪律是时间窗。大表没有时间条件,不跑。第三纪律是粒度。GROUP BY 的键必须和问题里的维度一一对应。
一对多关联会把头上的金额按明细复制,看起来像增长,其实是扇形。COUNT 和 COUNT DISTINCT 不是同一指标。NULL 不是 0。日期函数没有世界语,能写绝对区间就写绝对区间。
复杂逻辑用公共表表达式拆开。拆开是为了给人看中间结果。先对再快。用索引去救一条口径错误的语句,会把错误生产化。
读完这一辑可以做什么
把你最近一条问数语句拆成三段 WITH:过滤、聚合、排名。每一段单独跑。有一段解释不清,就回到提问,不要在语句里继续加花样。
不等于取消,并不包含状态为空。三值逻辑会静静删行。