先 having 還是先 select?sql 子句執(zhí)行順序揭秘
sql 語(yǔ)句中,having 子句用于篩選組內(nèi)的記錄,而 select 子句用于選擇要顯示的列。那么,是先執(zhí)行 having 子句還是 select 子句呢?
傳統(tǒng)觀點(diǎn)認(rèn)為,先執(zhí)行 having 子句,然后再執(zhí)行 select 子句。然而,示例代碼中似乎與這一觀點(diǎn)相悖。代碼如下:
SELECT sum(num) AS all_num FROM table GROUP BY id HAVING all_num > 50
執(zhí)行結(jié)果顯示,先執(zhí)行了 select 語(yǔ)句,即計(jì)算了 all_num,然后再執(zhí)行 having 子句,對(duì)分組后的結(jié)果進(jìn)行了篩選。
原因
這種現(xiàn)象背后的原因并非 having 子句優(yōu)先執(zhí)行,而是因?yàn)?select 語(yǔ)句在 sql 中具有雙重作用。
一方面,select 子句可以用于選擇要顯示的列。但在本例中,select 語(yǔ)句沒(méi)有選擇任何現(xiàn)有列,而是生成了一個(gè)新列 all_num。因此,在這個(gè)例子中,select 語(yǔ)句不執(zhí)行任何選擇性操作。
另一方面,select 語(yǔ)句也可以用于聚合函數(shù)。本例中,select 語(yǔ)句計(jì)算了每個(gè)組的 num 列的總和,并將結(jié)果存儲(chǔ)在 all_num 列中。因此,在此場(chǎng)景下,select 語(yǔ)句實(shí)際上是一個(gè)聚合操作。
執(zhí)行順序
當(dāng) select 語(yǔ)句包含聚合函數(shù)時(shí),sql 引擎的執(zhí)行順序如下:
- 分組(group by 子句)
- 聚合(select 子句中的聚合函數(shù))
- 篩選(having 子句)
- 選擇(select 子句選擇要顯示的列)
因此,在示例代碼中,正確的執(zhí)行順序是:
- 按 id 列分組
- 計(jì)算每個(gè)組的 num 列的總和,并將其存儲(chǔ)在 all_num 列中
- 篩選出 all_num 大于 50 的組
- 選擇 all_num 列顯示結(jié)果