SQL过滤中CASE与OR的用法差异及相关技术疑问
Great catch on the redundant code in that DataCamp example! Your proposed alternative using AND/OR is absolutely cleaner and more practical. Let's walk through your questions one by one:
1. 此类在过滤中使用CASE子句的写法是否有特定原因?还是仅为DataCamp的教学演示,不具备实用性?
这种写法几乎没有生产环境的实用价值,它的存在大概率是为了教学目的:
- 可能是为了强化你对
CASE表达式语法的理解,展示CASE不仅能在SELECT中生成计算列,还能在其他子句(比如WHERE)中使用; - 也可能是为了直观演示“如何筛选出
CASE生成非空值的行”,但这是一种非常绕的方式。
在实际工作中,没人会这么写——你的AND/OR组合写法更高效、易读,也更容易维护。
2. 第一个查询中,过滤用CASE子句里分配分类的作用是什么?
这个CASE子句的核心作用是给符合条件的行生成一个非空字符串标记,不符合条件的行生成NULL,然后通过WHERE ... IS NOT NULL来筛选出那些符合条件的行。
本质上它和你的AND/OR逻辑是等价的:都是筛选“切尔西主场赢球”或“切尔西客场赢球”的记录。只不过它用了一种间接的方式——通过返回字符串的非空性来判断是否符合条件,而不是直接用布尔逻辑表达式。
3. 既然基于CASE过滤,为何不直接使用WHERE outcome IS NOT NULL?若仅为教学演示,是否存在该冗余写法的深层复杂原因?
这里的关键是SQL的执行顺序:数据库会先执行WHERE子句来筛选行,然后才会执行SELECT子句来计算列(包括你定义的别名outcome)。这意味着在WHERE子句执行时,outcome这个列还没有被计算出来,所以直接写WHERE outcome IS NOT NULL会触发语法错误。
DataCamp的例子重复CASE逻辑,其实是为了绕过这个执行顺序的限制,但这是一种非常冗余的做法。实际工作中,你要么用你提出的AND/OR组合写法(最优解),要么用子查询或CTE先计算outcome再过滤,比如:
WITH match_outcomes AS ( SELECT date, season, CASE WHEN hometeam_id = 8455 AND home_goal > away_goal THEN 'Chelsea home win!' WHEN awayteam_id = 8455 AND home_goal < away_goal THEN 'Chelsea away win!' END AS outcome FROM match ) SELECT date, season, outcome FROM match_outcomes WHERE outcome IS NOT NULL;
但显然你的直接过滤写法比这个更简洁高效。
内容的提问来源于stack exchange,提问作者Yehuda

