开发者

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >=

开发者 https://www.devze.com 2023-03-25 11:22 出处:网络
I have run into a road block. I am trying to retrieve summed data from the database using a query that consists of 5 subqueries in the select . I need to return multiple rows for each column so this i

I have run into a road block. I am trying to retrieve summed data from the database using a query that consists of 5 subqueries in the select . I need to return multiple rows for each column so this is what i have.

  select distinct ISNULL((select sum(i.Amount) from invoice i inner join vSchool v on  v.SchoolID = i.SchoolID and v.SystemID = '617'
    inner join request R on R.requestid = i.requestid
    where i.SchoolID =       v.SchoolID                                       
    and i.ReimbursementTypeID = '28'            
    and month(R.FundMonth)='2'
    and R.requesttypeID = '32'                                         
    group by v.SchoolID),0) as FVTotal
   ,ISNULL((select sum(i.Amount) from invoice i inner join vSchool v on v.SchoolID =   i.SchoolID and v.SystemID = '617'
   inner join request R on R.requestid = i.requestid
   inner join grantsystem G on G.grantsystemID = R.grantsystemID
   inner join grants GR on GR.grantsid = G.grantsID
   where i.SchoolID = v.SchoolID                                          
   and i.ReimbursementTypeID = '29'         
  and month(R.FundMonth)='2'
  and R.requesttypeID = '32'                                       
  and GR.grantsid = '5' or GR.grantsid = '7'
  group by v.schoolid),0)  as OpLaborTotal
  ,ISNULL((select sum(i.Amount) from invoice i inner join vSchool v on v.SchoolID =   i.SchoolID and v.SystemID = '617'
  inner join request R on R.requestid = i.requestid
  where i.SchoolID =   v.SchoolID                                         
 and i.ReimbursementTypeID = '31'           
 and month(R.FundMonth)='2'
 and R.requesttypeID = '32'                                        
 group by v.schoolid),0)  as SupplyTotal
 ,ISNULL((select sum(i.Amount) from invoice i inner join vSchool v on v.SchoolID =   i.SchoolID and v.SystemID = '617'
 inner join request R on R.requestid = i.requestid
 where i.SchoolID = v.SchoolID                                        
 an开发者_运维知识库d i.ReimbursementTypeID = '30'           
 and month(R.FundMonth)='2'
 and R.requesttypeID = '32'                                        
 group by v.schoolid),0) as LargeTotal
,ISNULL((select sum(i.Amount) from invoice i inner join vSchool v on v.SchoolID =   i.SchoolID and v.SystemID = '617'
inner join request R on R.requestid = i.requestid
inner join grantsystem G on G.grantsystemID = R.grantsystemID
inner join grants GR on GR.grantsid = G.grantsID
where i.SchoolID = v.SchoolID                                         
and i.ReimbursementTypeID = '29'            
and month(R.FundMonth)='2'
and R.requesttypeID = '32'                                         
and GR.grantsid = '6' or GR.grantsid = '8'
group by v.schoolid),0) as AdminLabor

This query gives me the error about multiple values being returned.. Is there a workaround that will allow me to do what I am trying to do here?


A possible complete refactor of your query to avoid the massive headache and duplication cause by the sub-queries...

SELECT
  v.schoolid
  ISNULL(SUM(CASE WHEN i.ReimbursementTypeID = '28'                              THEN i.Amount END),0)  as FVTotal,
  ISNULL(SUM(CASE WHEN i.ReimbursementTypeID = '29' AND GR.grantsid IN ('5','7') THEN i.Amount END),0)  as OpLaborTotal,
  ISNULL(SUM(CASE WHEN i.ReimbursementTypeID = '31'                              THEN i.Amount END),0)  as SupplyTotal,
  ISNULL(SUM(CASE WHEN i.ReimbursementTypeID = '30'                              THEN i.Amount END),0)  as LargeTotal,
  ISNULL(SUM(CASE WHEN i.ReimbursementTypeID = '29' AND GR.grantsid IN ('6','8') THEN i.Amount END),0)  as AdminLabor
FROM
  invoice i
INNER JOIN
  vSchool v
    ON  v.SchoolID = i.SchoolID
    AND v.SystemID = '617'
INNER JOIN
  request R
    ON R.requestid = i.requestid
LEFT JOIN
  grantsystem G
    ON G.grantsystemID = R.grantsystemID
LEFT JOIN
  grants GR
    ON GR.grantsid = G.grantsID
WHERE
  MONTH(R.FundMonth)  = '2'    
  AND R.requesttypeID = '32'
GROUP BY
  v.SchoolID  

NOTE: You've encase all your IDs in quotes. Are the IDs really strings? If they're numerics, don't use the quotes :)


The query is too big for me to want to re-format it all and work out all the joins. But there is possibly a quick and dirty fix for you...

Make the selection FROM the vSchool table, and then turn your sub-queries into correlated-sub-queries, by referencing the outer instance of vSchool...

select  main.schoolid,
        ,ISNULL((select sum(i.Amount) from invoice i inner join vSchool v on v.SchoolID = i.SchoolID and v.SystemID = '617'
                                          inner join request R on R.requestid = i.requestid
                                          where i.SchoolID = v.SchoolID                                       
                                          and i.ReimbursementTypeID = '28'          
                                          and month(R.FundMonth)='2'
                                          and R.requesttypeID = '32'                                       
                                          AND v.schoolid = main.schoolid),0) as FVTotal
        ,ISNULL((select sum(i.Amount) from invoice i inner join vSchool v on v.SchoolID = i.SchoolID and v.SystemID = '617'
                                          inner join request R on R.requestid = i.requestid
                                          inner join grantsystem G on G.grantsystemID = R.grantsystemID
                                          inner join grants GR on GR.grantsid = G.grantsID
                                          where i.SchoolID = v.SchoolID                                       
                                          and i.ReimbursementTypeID = '29'          
                                          and month(R.FundMonth)='2'
                                          and R.requesttypeID = '32'                                       
                                          and (GR.grantsid = '5' or GR.grantsid = '7')
                                          AND v.schoolid = main.schoolid),0)  as OpLaborTotal
        ,ISNULL((select sum(i.Amount) from invoice i inner join vSchool v on v.SchoolID = i.SchoolID and v.SystemID = '617'
                                          inner join request R on R.requestid = i.requestid
                                          where i.SchoolID = v.SchoolID                                       
                                          and i.ReimbursementTypeID = '31'          
                                          and month(R.FundMonth)='2'
                                          and R.requesttypeID = '32'                                       
                                          AND v.schoolid = main.schoolid),0)  as SupplyTotal
        ,ISNULL((select sum(i.Amount) from invoice i inner join vSchool v on v.SchoolID = i.SchoolID and v.SystemID = '617'
                                          inner join request R on R.requestid = i.requestid
                                          where i.SchoolID = v.SchoolID                                       
                                          and i.ReimbursementTypeID = '30'          
                                          and month(R.FundMonth)='2'
                                          and R.requesttypeID = '32'                                       
                                          AND v.schoolid = main.schoolid),0) as LargeTotal
        ,ISNULL((select sum(i.Amount) from invoice i inner join vSchool v on v.SchoolID = i.SchoolID and v.SystemID = '617'
                                          inner join request R on R.requestid = i.requestid
                                          inner join grantsystem G on G.grantsystemID = R.grantsystemID
                                          inner join grants GR on GR.grantsid = G.grantsID
                                          where i.SchoolID = v.SchoolID                                       
                                          and i.ReimbursementTypeID = '29'          
                                          and month(R.FundMonth)='2'
                                          and R.requesttypeID = '32'                                       
                                          and (GR.grantsid = '6' or GR.grantsid = '8')
                                          AND v.schoolid = main.schoolid),0) as AdminLabor
FROM
  vSchool AS [main]

I'm almost positive that you can refactor that query into something much less cumbersome, but as I said, there is too much in there for me to want to unravel it, sorry.


Solution if you don't need sums per school

I'm taking an educated guess here and say you should just remove all the group by clauses in the subqueries, as you don't seem to really care about sums per school. You seem to want overall sums. So you don't need to group by. Then you'll have only one record containing a single sum in every subquery.

Solution if you do need sums per school

If you do need the grouping (i.e. if you need sums per school), then maybe you should rephrase your query to something like this:

select 'fvtotal' as type,
       sum(amount) as total,
       schoolid as schoolid
from ... -- first filtered table source here
group by schoolid

union

select 'oplabortotal' as type,
       sum(amount) as total,
       schoolid as schoolid
from ... -- second filtered table source here
group by schoolid

union

-- etc

This will result in a table of this form

+------------+-----------+---------+
|type        | total     | schoolid|
+------------+-----------+---------+
|fvtotal     |1234       |1        |
|fvtotal     |32985      |2        |
|oplabortotal|341        |1        |
|...         |           |         |
+------------+-----------+---------+


No offense, but this query...well nevermind. It didn't actually crawl off the page and bite somebody when I was reading it, so I'll bite my tongue.

Your use of ISNULL() seems odd.

Try this. Instead of this format:

ISNULL(
    (select sum(i.Amount) 
     from invoice i 
     inner join vSchool v 
     on  v.SchoolID = i.SchoolID 
     and v.SystemID = '617'
     inner join request R 
     on R.requestid = i.requestid
     where i.SchoolID = v.SchoolID                                       
     and i.ReimbursementTypeID = '28'            
     and month(R.FundMonth)='2'
     and R.requesttypeID = '32'                                         
     group by v.SchoolID),0) as FVTotal

Try this instead

(select sum(isnull(i.Amount,0)) 
     from invoice i 
     inner join vSchool v 
     on  v.SchoolID = i.SchoolID 
     and v.SystemID = '617'
     inner join request R 
     on R.requestid = i.requestid
     where i.SchoolID = v.SchoolID                                       
     and i.ReimbursementTypeID = '28'            
     and month(R.FundMonth)='2'
     and R.requesttypeID = '32'                                         
     group by v.SchoolID) as FVTotal

Do that for each subquery...

PS -- this query is very badly written in general. You should consider an overhaul, seriously.


Yes, you can make the query run by having each subselect SELECT TOP 1.

Bear in mind however that you're losing data you apparently want to select here, so this is probably not the ideal solution!


I would do something more like

select 
    i.ReimbursementTypeID, GR.grantsid, v.SchoolID, sum(i.Amount) as Total 
from 
    invoice i inner join vSchool v on  v.SchoolID = i.SchoolID  inner join request R on R.requestid = i.requestid
    left outer join grantsystem G on G.grantsystemID = R.grantsystemID left outer join grants GR on GR.grantsid = G.grantsID
where   
    v.SystemID = '617'                                    
    and ((i.ReimbursementTypeID in('28','30','31')) or  (i.ReimbursementTypeID = '29' and GR.grantsid in('5', '6', '7','8')))
    and month(R.FundMonth)='2'
    and R.requesttypeID = '32'                                         
group by 
    i.ReimbursementTypeID, GR.grantsid, v.SchoolID

You only want your join and where criteria once, not once per reimbursementTypeID/grantsID and you can group by those field values to create your parallel sums.

0

精彩评论

暂无评论...
验证码 换一张
取 消