请写出一个 SQL 查询,找出那些名下至少存在一个订单其金额大于 200 的客户,并返回这些客户的姓名。
考察说明
考查对 SQL 分组、聚合或子查询与条件过滤的综合应用能力,以及能否用正确且高效的写法解决‘至少一次’类业务查询。
回答思路
- 【回答框架 1】该查询的语义是筛选出至少有一个订单金额超过 200 的客户,而不是所有订单金额均超过 200。常见实现方式是使用 EXISTS 子查询,连接订单表并过滤金额大于 200,再关联客户表返回姓名,这样能在找到首个满足条件的订单后提前终止,通常效率较高。
- 【回答框架 2】另一种写法是使用 IN 子查询,先从订单表中选出金额大于 200 的不重复客户编号,再在客户表中用 WHERE IN 过滤。该写法逻辑清晰,但若订单表较大且金额条件选择性不高,可能存在性能开销。
- 【回答框架 3】还可以采用 JOIN 加 GROUP BY 与 HAVING 的方式,对订单表按客户编号分组,并设置 HAVING MAX(订单金额) > 200 或 COUNT(SUM(条件)) 等条件,然后与客户表关联。这种方式需要先分组,可能带来较大中间结果,在数据量小或 SQL 优化器可下推时也可行。
- 【回答框架 4】实际生产中,建议结合索引情况选择:订单表(客户编号、金额)上的复合索引能显著加速 EXISTS 或内连接。若客户表很小而订单表很大,EXISTS 通常较优;若两者规模相近,IN 与 EXISTS 优化后可能等价。
- 【关键点 1】使用 EXISTS 或 IN 子查询可准确表达‘至少一个’语义。
- 【关键点 2】使用 JOIN 时需要用 DISTINCT 去重,防止同一客户因多个满足条件的订单而被重复返回。
- 【关键点 3】若选用 GROUP BY 方案,需用 HAVING 配合条件表达式,例如 SUM(CASE WHEN 金额 > 200 THEN 1 ELSE 0 END) > 0。
- 【易错点 1】避免直接用 JOIN 后不加 DISTINCT,因为一个客户可能有多个超 200 的订单,导致客户姓名重复出现。
- 【易错点 2】注意金额字段的数据类型,若为浮点数,比较时需考虑精度,但一般业务上直接比较即可。
- 【易错点 3】不要误写为 ‘所有订单金额都大于 200’ 的条件,例如使用 MIN(金额) > 200,那将改变查询语义。