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.
精彩评论