当我们遇到复杂 SQL 子查询的时候,发现表经常被复用的情况,按照传统的写法,就需要子查询 SQL 重复写,这样 SQL 很不优雅,今天我们用 WITH AS 来解决这个问题!(MySQL 8.0+ 开始支持)
WITHt2AS( WITHt1AS( SELECTid, visit_date, peopleFROMStadiumWHEREpeople>=100 ) SELECTid, visit_date, people, :=IF(id-=1, , +1) groupId, :=idFROMt1, (SELECT :=(SELECTidFROMt1LIMIT0, 1), :=0) init) SELECTid, visit_date, peopleFROMt2WHEREgroupIdIN ( SELECTgroupIdFROMt2GROUPBYgroupIdHAVINGCOUNT(groupId) >=3)
我们可以看到好多地方用到了 t1 和 t2,如果都采取传统子查询写法,我估计你要奔溃,而且没自信是否能一把过!
这里还有个地方需要注意,这里的临时表有 2 个,除了上面的嵌套的写法外,还可以这样写:
WITHcte1AS( select*fromtable1wherenamelike'abc%'), cte2AS( select*fromtable2whereid>20), cte3AS( select*fromtable3whereprice<100) selecta.*fromcte1a, cte2b, cte3cwherea.id=b.idanda.id=c.id
- 这样有一个好处是:可以多个临时表被最后的 SELECT 语句复用,否则嵌套里面的临时表是无法被最后的 SELECT 复用的。
但是绝对不能下面这种写法:
// 反例: 运行错误WITHt1AS( SELECTid, visit_date, peopleFROMStadiumWHEREpeople>=100) WITHt2AS( SELECTid, visit_date, people, :=IF(id-=1, , +1) groupId, :=idFROMt1, (SELECT :=(SELECTidFROMt1LIMIT0, 1), :=0) init)