MS SQL报错:子查询返回多个值,求排查解决(附SQL语句)
搞定MS SQL的“Subquery returned more than 1 value”报错
兄弟,你这个报错太常见了——说白了就是你写的那两个子查询,返回了不止一行数据,但主查询每一行只能对应子查询的一个值,数据库懵了就给你抛错了。咱们来一步步拆解问题和解决办法:
问题出在哪?
看你的SQL语句,有两个嵌在SELECT里的标量子查询:
(select name from tb_Category where id = Category) AS Category(select Amount from tb_innovatorDisbursement where tbid ='TBINO1111A' and applyingforcycle='1') AS AmountDisbursed
标量子查询的规则很死:必须返回0条或者1条结果。现在这俩里面至少有一个查出了好几条记录,数据库直接给你报错。
举个例子:
- 第一个子查询:可能
tb_Category里有好几个id和当前行的Category值一样; - 第二个子查询:
tb_innovatorDisbursement里符合tbid='TBINO1111A' and applyingforcycle='1'的记录不止一条,比如同一个项目分多次打款的情况。
怎么解决?
根据你的业务需求,有三种常用的处理方式:
1. 让子查询只返回一条结果
如果业务上每个主查询行对应的子查询本来就应该只有一个匹配项,那要么检查数据,要么给子查询加TOP 1(最好再加排序,确定返回哪一条):
select Id,Prayaseeid, name,Gender, -- 加TOP 1确保只返回一个分类名,按创建时间取最新的 (select TOP 1 name from tb_Category where id = Category ORDER BY CreatedDate DESC) AS Category, ideadescription,Domain,ProjectTerms,ProjectStartDate,Amountsanctioned, -- 同理,取最新的一笔打款金额 (select TOP 1 Amount from tb_innovatorDisbursement where tbid ='TBINO1111A' and applyingforcycle='1' ORDER BY DisbursementDate DESC) AS AmountDisbursed, projectstatus,projectoutcome from tb_innovator where tbid='TBINO1111A' and applyingforcycle='1'
2. 用聚合函数汇总多行结果
如果业务上需要把多行数据合并成一个值(比如总打款金额、最大打款额),用聚合函数就对了:
select Id,Prayaseeid, name,Gender, (select name from tb_Category where id = Category) AS Category, ideadescription,Domain,ProjectTerms,ProjectStartDate,Amountsanctioned, -- 计算总打款金额 (select SUM(Amount) from tb_innovatorDisbursement where tbid ='TBINO1111A' and applyingforcycle='1') AS AmountDisbursed, projectstatus,projectoutcome from tb_innovator where tbid='TBINO1111A' and applyingforcycle='1'
常用的聚合函数还有MAX()(取最大金额)、MIN()(取最小)、AVG()(取平均),按需选就行。
3. 改用JOIN关联查询(展示所有匹配结果)
如果业务上需要把主表行和子表的所有匹配行都展示出来(比如同一个项目的每笔打款都单独一行),那别用子查询了,换成JOIN:
select i.Id,i.Prayaseeid, i.name,i.Gender, c.name AS Category, i.ideadescription,i.Domain,i.ProjectTerms,i.ProjectStartDate,i.Amountsanctioned, d.Amount AS AmountDisbursed, i.projectstatus,i.projectoutcome from tb_innovator i -- 左关联分类表,确保主表行即使没有分类也能显示 left join tb_Category c on c.id = i.Category -- 左关联打款表,每一笔打款对应一行结果 left join tb_innovatorDisbursement d on d.tbid = i.tbid and d.applyingforcycle = i.applyingforcycle where i.tbid='TBINO1111A' and i.applyingforcycle='1'
这种方式会返回主表行和子表匹配行的组合,如果子表有多行,主表行会重复显示对应子表的每一行。
小提示
- 先单独跑一下子查询,比如执行
select name from tb_Category where id = [主表里某个Category的值],看看是不是真的返回了多行,这样能快速定位问题; - 检查
tb_Category的id是不是主键,如果是主键的话,第一个子查询就不会返回多行,这可能是数据的问题哦。
内容的提问来源于stack exchange,提问作者sanjay prajapati
相关产品推荐
相关产品推荐

