You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL查询未加指定筛选分组时返回多行而非预期单行的问题咨询

enter image description here

问题相关SQL

原始查询语句:

select 
    t.customer_type,
    (case 
         when &a1 in (1, 2) and &a2 in ('AZN', 'USD', 'ALL') 
             then (select t.balance_no from test12 t 
                   where t.customer_type = &a1 and t.currency = &a2)
         when &a1 in (1, 2) and &a2 not in ('AZN', 'USD', 'ALL') 
             then (select t.balance_no from test12 t 
                   where t.customer_type = &a1 and t.currency = 'ALL') 
     end)
from 
    test12 t
where 
    t.customer_type = &a1
group by 
    t.customer_type;

如果移除末尾的筛选、分组逻辑:

where t.customer_type = &a1
group by t.customer_type

查询会返回和test12表总行数一致的结果,而非预期的单行结果。核心疑问:CASE语句的子查询中已经写了t.customer_type=&a1 and t.currency=&a2的筛选条件,为什么外层不加上述逻辑就会返回全表行数的结果?

原因说明
  • SQL的执行顺序是优先处理FROM子句加载表数据,再依次处理WHERE过滤、GROUP BY分组,最后才会计算SELECT后面的字段值。外层写了from test12 t又没加WHERE过滤条件时,第一步生成的基础结果集就是test12的全量行,和SELECT里写了什么计算逻辑没有任何关系。
  • 写在CASE里的子查询属于标量子查询,作用仅仅是给基础结果集里的每一行计算出一个对应的列值,既不会过滤外层的行,也不会自动合并重复行。举个最简单的例子:写select id, (select '固定文本') from user,不管子查询返回什么固定内容,最终结果行数永远和user表的总行数一致。
  • 子查询内部写的筛选条件只约束子查询自身的返回结果,完全不会影响外层FROM加载的行数。你当前写的子查询本身只会返回一个固定的balance_no值,效果等同于给全表每一行都拼上同一个固定字段值,自然会返回全表行数。
  • 你额外加的两段逻辑才是控制返回行数的核心:where t.customer_type = &a1先把外层全表数据过滤到只剩对应客户类型的行,group by t.customer_type再把同客户类型的多行合并为1行,最终才能得到你预期的单行结果。

额外注意:子查询里给test12起的别名也叫t,和外层表别名重名,虽然当前子查询没有引用外层字段不会触发关联逐行计算,但这种写法非常容易因为别名混淆写出逻辑bug,建议子查询换个不同的别名比如t_sub。

内容的提问来源于stack exchange,提问作者deku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:06:29