鸣潮自动化助手:基于视觉识别的智能游戏辅助解决方案
2026/5/31 21:02:10
SELECT子句本身并不用于直接过滤数据行,而是用于表达式计算和返回结果列。
但有两种特殊“伪过滤”情况,初学者容易混淆:
CASE WHEN生成标志位SELECTid,amount,CASEWHENamount>500THEN'大额'ELSE'小额'ENDASgradeFROMorders;这里只是标记,并没有“过滤”数据行。
FILTERSELECTSUM(amount)FILTER(WHEREtype='A')ASsum_a,SUM(amount)FILTER(WHEREtype='B')ASsum_bFROMorders;这里的FILTER是对聚合函数的聚合过滤,不影响整行是否被选中,只决定聚合时哪些被算上。
SELECT 不能直接过滤结果行(除了各种聚合“过滤”标志)。真正过滤结果应放在WHERE或JOIN或HAVING。
JOIN的ON部分与WHERE条件不同:
SELECT*FROMaJOINbONa.id=b.a_idANDb.status='active'b.status = 'active'写在ON内,只有满足 a.id=b.a_id 且 b.status=‘active’ 时,才产生一对结果。SELECT*FROMaLEFTJOINbONa.id=b.a_idANDb.status='active'LEFT JOIN不管 b 有无匹配,总会保留 a。ON过滤是:如果 b.status 不为 ‘active’,则 b 列为 NULL;不会把整行 a 去掉。SELECT*FROMaLEFTJOINbONa.id=b.a_idWHEREb.status='active'WHERE条件会把 a 的那些 b 没有匹配到的(所有 b 为 NULL 的)全部去掉,实际上结果和 INNER JOIN 效果一样!WHERE负责数据源(包括 join 后的中间结果)的最终行过滤。
SELECT*FROMaJOINbONa.id=b.a_idWHEREa.amount>100ANDb.status='active'假如有如下两个表:
假设每个学生有多个成绩。
条件写在JOIN:
SELECTs.id,s.name,sc.markFROMstudents sJOINscores scONs.id=sc.student_idANDsc.mark>=60🚩只有及格的匹配行会被连接,学生不会重复出现不及格的成绩。
条件写在WHERE:
SELECTs.id,s.name,sc.markFROMstudents sJOINscores scONs.id=sc.student_idWHEREsc.mark>=60🚩结果一样:只显示及格成绩。
LEFT JOIN + 过滤条件写在JOIN:
SELECTs.id,s.name,sc.markFROMstudents sLEFTJOINscores scONs.id=sc.student_idANDsc.mark>=60🚩每个学生会显示所有自己及格的成绩,没及格就为 NULL,但学生都在。
LEFT JOIN + 过滤条件写在WHERE:
SELECTs.id,s.name,sc.markFROMstudents sLEFTJOINscores scONs.id=sc.student_idWHEREsc.mark>=60🚩所有没及格的行(包括没考试的、sc.mark是NULL),全部被过滤掉,效果和INNER JOIN一样!
| 过滤条件位置 | 作用对象 | 推荐场景 |
|---|---|---|
| SELECT | 只对输出列做条件标记、赋值 | 需展示条件分组/标识 |
| JOIN (ON) | 只影响表之间的连接配对关系 | 只过滤被联接表时,主表全保留 |
| WHERE | 影响整个结果最终输出行 | 需要严格筛选全部输出的情况 |
LEFT JOIN ... ON ...WHEREJOIN ON