SQL Logic for Multi-Matches - sql

I have a situation where I am pulling back data from several tables MEMBERS, SS, and SSUSED. Where 'MEMBERS' is the table with member data, 'SS' is the table with the products that a member has purchased on their account and SSUSED is a table that stores the usage of the products. Products can have 1, 6 or 12 usages. So there can be a one to one, one to six, or one to twelve matching ratio. When I run my query, I am bringing back all of the usages. I only need to bring back the latest one (SSUSED.usedate).
I am also trying to filter out certain products and product categories and that doesn't seem to be totally working. I get a random product here and there and I can not seem to isolate the issue. I think it may be because my logic isn't written in a clean efficient manner.
CODE:
SELECT DISTINCT
MEMBERS.scancode, MEMBERS.lname, MEMBERS.fname, MEMBERS.mtypeid, MEMBERS.status, MEMBERS.lastvisit, MEMBERS.datejoin,
PRODUCTS.description, EMPLOYEES.lname AS EmpLname, EMPLOYEES.fname AS EmpFName, SSUSED.transactiontype, SS.initialdate, SS.initialquantity,
SS.usedquantity, MEMBERTYPES.mtype, SS.ssid, SSUSED.usedate
FROM PRODUCTCATS INNER JOIN
PRODUCTS ON PRODUCTCATS.productcatid = PRODUCTS.productcatid INNER JOIN
SS ON PRODUCTS.productid = SS.productid INNER JOIN
MEMBERS ON SS.memid = MEMBERS.memid LEFT OUTER JOIN
SSUSED ON SS.ssid = SSUSED.ssid INNER JOIN
EMPLOYEES ON SSUSED.employeeid = EMPLOYEES.employeeid INNER JOIN
MEMBERTYPES ON MEMBERS.mtypeid = MEMBERTYPES.mtypeid
WHERE (SS.memid IN
(SELECT DISTINCT SS_1.memid
FROM SS AS SS_1 INNER JOIN
SSUSED AS SSUSED_1 ON SS_1.ssid = SSUSED_1.ssid INNER JOIN
MEMBERS AS MEMBERS_1 ON SS_1.memid = MEMBERS_1.memid
WHERE (MEMBERS_1.siteid = #rvSite) AND (SS_1.productid = '324' OR
SS_1.productid = '326') AND (SSUSED_1.usedate BETWEEN #rvStartDate AND #rvEndDate) AND (SSUSED_1.transactiontype = 'Use'))) AND
(PRODUCTS.productcatid = '27' OR
PRODUCTS.productcatid = '28' OR
PRODUCTS.productcatid = '29' OR
PRODUCTS.productcatid = '58' OR
PRODUCTS.productcatid = '77' OR
PRODUCTS.productcatid = '75' OR
PRODUCTS.productcatid = '30' OR
PRODUCTS.productcatid = '61' OR
PRODUCTS.productcatid = '31' OR
PRODUCTS.productcatid = '32' OR
PRODUCTS.productcatid = '47' OR
PRODUCTS.productcatid = '68') AND (SS.productid <> '32' OR
SS.productid <> '335' OR
SS.productid <> '350' OR
SS.productid <> '618' OR
SS.productid <> '1312' OR
SS.productid <> '1646' OR
SS.productid <> '54987' OR
SS.productid <> '55937' OR
SS.productid <> '58289' OR
SS.productid <> '58876' OR
SS.productid <> '601691') AND (SSUSED.transactiontype = 'Use' OR
SSUSED.transactiontype = 'Expired') AND (SSUSED.usedate >= #rvStartDate)

This doesn't really answer the question but demonstrates how much cleaner this query can be with some formatting, aliases and converting those huge lists into IN predicates.
SELECT DISTINCT m.scancode
, m.lname
, m.fname
, m.mtypeid
, m.STATUS
, m.lastvisit
, m.datejoin
, p.description
, e.lname AS EmpLname
, e.fname AS EmpFName
, su.transactiontype
, SS.initialdate
, SS.initialquantity
, SS.usedquantity
, mt.mtype
, SS.ssid
, su.usedate
FROM PRODUCTCATS pc
INNER JOIN PRODUCTS p ON pc.productcatid = p.productcatid
INNER JOIN SS ON p.productid = SS.productid
INNER JOIN MEMBERS m ON SS.memid = m.memid
LEFT JOIN SSUSED su ON SS.ssid = su.ssid
INNER JOIN EMPLOYEES e ON su.employeeid = e.employeeid
INNER JOIN MEMBERTYPES mt ON m.mtypeid = mt.mtypeid
WHERE SS.memid IN
(
SELECT DISTINCT SS_1.memid
FROM SS AS SS_1
INNER JOIN SSUSED AS SSUSED_1 ON SS_1.ssid = SSUSED_1.ssid
INNER JOIN MEMBERS AS MEMBERS_1 ON SS_1.memid = MEMBERS_1.memid
WHERE MEMBERS_1.siteid = #rvSite
AND SS_1.productid in ('324', '326')
AND SSUSED_1.usedate BETWEEN #rvStartDate AND #rvEndDate
AND SSUSED_1.transactiontype = 'Use'
)
AND p.productcatid in('27', '28', '29', '58', '77', '75', '30', '61', '31', '32', '47', '68')
AND SS.productid in ('32', '335', '350', '618', '1312', '1646', '54987', '55937', '58289', '58876', '601691')
AND su.transactiontype in ('Use', 'Expired'
AND su.usedate >= #rvStartDate
To actually be able to help with the question we need some understanding of what this is supposed to be doing and what isn't working.

Related

SQL Server : SUM DISTINCT GROUP BY

I'm currently creating a query to sum the code below
select distinct
opch.docentry as 'AP Invoice #',
pch1.linenum as 'AP Invoice Line #',
pch1.itemcode as 'Item Code',
pch1.dscription as 'Item Name',
pch1.freetxt as 'Free Text',
pch1.priceafvat as 'Gross Price',
pch1.quantity as 'Quantity',
pch1.gtotal as 'Gross Total'
from
opch
inner join
pch1 on opch.docentry = pch1.docentry
inner join
opdn on opdn.docentry = pch1.basedocnum
inner join
pdn1 on opdn.docentry = pdn1.docentry
inner join
opor on opor.docentry = pdn1.basedocnum
inner join
por1 on opor.docentry = por1.docentry
where
pch1.u_budgetno = '57'
and opch.canceled = 'N'
and opdn.docstatus = 'C'
and opdn.canceled = 'N'
and opor.docstatus = 'C'
and opor.canceled = 'N'
order by
opch.docentry
This is the sum statement I've tried
select
opch.docentry,
sum(pch1.gtotal)
from
opch
inner join
pch1 on opch.docentry = pch1.docentry
inner join
opdn on opdn.docentry = pch1.basedocnum
inner join
pdn1 on opdn.docentry = pdn1.docentry
inner join
opor on opor.docentry = pdn1.basedocnum
inner join
por1 on opor.docentry = por1.docentry
where
pch1.u_budgetno = '57'
and opch.canceled = 'N'
and opdn.docstatus = 'C'
and opdn.canceled = 'N'
and opor.docstatus = 'C'
and opor.canceled = 'N'
group by
opch.docentry, opdn.docstatus
It however doesn't return the correct amount as it duplicates some answers based on the connected tables.
Requesting assistance on what I'm doing wrong.
*Update
This is the result from the select distinct query
enter image description here
I'm aiming for the sum query to sum the results from the pch1.gtotal column
Thank you.
The problem is in the join you are doing between the invoice and the delivery note. You are not joining the line so it multiplies the results. The correct join is done using BaseEntry, BaseLine and BaseType. The same applies to the join with the purchase order.
select
opch.docentry,
sum(pch1.gtotal)
from
opch
inner join
pch1 on opch.docentry = pch1.docentry
inner join
pdn1 on pdn1.docentry = pch1.baseentry and pdn1.linenum = pch1.baseline and pdn1.objtype = pch1.basetype
inner join
opdn on opdn.docentry = pdn1.docentry
inner join
por1 on por1.docentry = pdn1.baseentry and por1.linenum = pdn1.baseline and por1.objtype = pdn1.basetype
inner join
opor on opor.docentry = por1.docentry
where
pch1.u_budgetno = '57'
and opch.canceled = 'N'
and opdn.docstatus = 'C'
and opdn.canceled = 'N'
and opor.docstatus = 'C'
and opor.canceled = 'N'
group by
opch.docentry

SQL Nesting Logic Needed

I have a situation where I need to build a query that pulls gives me a list of member that used an item on their account in timeframe one but that did not use on item on their account in timeframe two.
SELECT DISTINCT SS.memid
FROM SS
INNER JOIN SSUSED ON SS.ssid = SSUSED.ssid
INNER JOIN MEMBERS AS MEMBERS_1 ON SS.memid = MEMBERS_1.memid
INNER JOIN PRODUCTS ON SS.productid = PRODUCTS.productid
INNER JOIN PRODUCTCATS ON PRODUCTS.productcatid = PRODUCTCATS.productcatid
INNER JOIN EMPLOYEES ON SSUSED.employeeid = EMPLOYEES.employeeid
AND NOT EXISTS
(
SELECT DISTINCT SS_1.memid
FROM SS AS SS_1
INNER JOIN SSUSED AS SSUSED_1 ON SS_1.ssid = SSUSED_1.ssid
INNER JOIN MEMBERS AS MEMBERS_1 ON SS_1.memid = MEMBERS_1.memid
INNER JOIN PRODUCTS AS PRODUCTS_1 ON SS_1.productid = PRODUCTS_1.productid
INNER JOIN PRODUCTCATS AS PRODUCTCATS_1 ON PRODUCTS_1.productcatid = PRODUCTCATS_1.productcatid
INNER JOIN EMPLOYEES AS EMPLOYEES_1 ON SSUSED_1.employeeid = EMPLOYEES_1.employeeid
WHERE
MEMBERS_1.siteid = #rvSite
AND SSUSED_1.usedate BETWEEN #rvStartWeek2
AND #rvEndWeek2
AND PRODUCTS_1.productcatid IN (27,28,29,58,77,75,30,61,31,32,47,68)
)
WHERE MEMBERS_1.siteid = #rvSite
AND SSUSED.usedate BETWEEN #rvStartWeek1
AND #rvEndWeek1
AND PRODUCTS.productcatid IN (27,28,29,58,77,75,30,61,31,32,47,68)
The issue that I am running into is that when I try the query this way I get the following error:

Issues With Excluding Results From Subquery

I am attempting to retrieve a list of members (MEMBERS table) who have purchased (ARTRANS table) a product from one of three product categories (PRODUCTCATS table) during a specified period (a month) and then have not purchased a product from that category in the following period (month).
Both queries work by themselves but when I put them together I do not pull any results. PLEASE HELP!
SELECT MEMBERS.lname
, MEMBERS.fname
, MEMBERS.email
, PRODUCTS.scancode
, PRODUCTS.description
, ARTRANS.datetrans
, ARTRANS.memid
, ARTRANS.invoice
, ARTRANSITEMS.price
, ARTRANSITEMS.quantity
FROM PRODUCTS
INNER JOIN ARTRANSITEMS
ON PRODUCTS.productid = ARTRANSITEMS.productid
INNER JOIN ARTRANS
ON ARTRANSITEMS.transid = ARTRANS.transid
INNER JOIN PRODUCTCATS
ON PRODUCTS.productcatid = PRODUCTCATS.productcatid
INNER JOIN MEMBERS
ON ARTRANS.memid = MEMBERS.memid
AND NOT EXISTS (
SELECT M2.memid
FROM PRODUCTS AS P2
INNER JOIN ARTRANSITEMS AS ATI
ON P2.productid = ATI.productid
INNER JOIN ARTRANS AS ART2
ON ATI.transid = ART2.transid
INNER JOIN PRODUCTCATS AS PC2
ON P2.productcatid = PC2.productcatid
INNER JOIN MEMBERS AS M2
ON ART2.memid = M2.memid
WHERE (
P2.productcatid = '20'
OR P2.productcatid = '21'
OR P2.productcatid = '78'
)
AND (ART2.datetrans BETWEEN DATEADD(month, 1, #rvMonthOneStart) AND DATEADD(month, 1, #rvMonthOneEnd))
)
WHERE (
PRODUCTS.productcatid = '20'
OR PRODUCTS.productcatid = '21'
OR PRODUCTS.productcatid = '78'
)
AND (ARTRANS.datetrans BETWEEN #rvMonthOneStart AND #rvMonthOneEnd)
Try this....
SELECT MEMBERS.lname, MEMBERS.fname, MEMBERS.email, PRODUCTS.scancode
, PRODUCTS.description, ARTRANS.datetrans, ARTRANS.memid
, ARTRANS.invoice, ARTRANSITEMS.price, ARTRANSITEMS.quantity
FROM PRODUCTS
INNER JOIN ARTRANSITEMS ON PRODUCTS.productid = ARTRANSITEMS.productid
INNER JOIN ARTRANS ON ARTRANSITEMS.transid = ARTRANS.transid
INNER JOIN PRODUCTCATS ON PRODUCTS.productcatid = PRODUCTCATS.productcatid
INNER JOIN MEMBERS ON ARTRANS.memid = MEMBERS.memid
WHERE PRODUCTS.productcatid IN ('20' ,'21','78')
AND (ARTRANS.datetrans BETWEEN #rvMonthOneStart AND #rvMonthOneEnd)
AND NOT EXISTS (SELECT 1
FROM PRODUCTS AS P2
INNER JOIN ARTRANSITEMS AS ATI ON P2.productid = ATI.productid
INNER JOIN ARTRANS AS ART2 ON ATI.transid = ART2.transid
INNER JOIN PRODUCTCATS AS PC2 ON P2.productcatid = PC2.productcatid
INNER JOIN MEMBERS AS M2 ON ART2.memid = M2.memid
WHERE PRODUCTS.productcatid IN ('20' ,'21','78')
AND (ART2.datetrans BETWEEN DATEADD(month, 1, #rvMonthOneStart) AND DATEADD(month, 1, #rvMonthOneEnd))
AND M2.memid = MEMBERS.memid)

SQL Statement Help Needed:Query within a Query

I am working on a query where I need to compile a list of of members who have a particular group of products associated with their, from a particular site and then for each member in that list retrieve all of the products on their account.
The first piece of the query is this:
SELECT
MEMBERS.memid
FROM
SITES
INNER JOIN
MEMBERS ON SITES.siteid = MEMBERS.siteid
INNER JOIN
SS ON MEMBERS.memid = SS.memid
INNER JOIN
PRODUCTCATS
INNER JOIN
PRODUCTS ON PRODUCTCATS.productcatid = PRODUCTS.productcatid
ON SS.productid = PRODUCTS.productid
INNER JOIN
EMPLOYEES ON SS.employeeid = EMPLOYEES.employeeid
WHERE
(PRODUCTS.productcatid = 77)
AND (SS.initialdate BETWEEN #rvPurchaseStart AND #rvPurchaseEnd)
From that list, I then need the following query to run for each member in that list:
SELECT
SITES.sitename, MEMBERS.scancode, MEMBERS.lname,
MEMBERS.fname, MEMBERS.mtypeid, MEMBERS.status,
PRODUCTS.description, SS.initialdate,
SS.initialquantity, SS.usedquantity, SS.dateexpire,
EMPLOYEES.lname AS Expr1, EMPLOYEES.fname AS Expr2
FROM
SITES
INNER JOIN
MEMBERS ON SITES.siteid = MEMBERS.siteid
INNER JOIN
SS ON MEMBERS.memid = SS.memid
INNER JOIN
PRODUCTCATS
INNER JOIN
PRODUCTS ON PRODUCTCATS.productcatid = PRODUCTS.productcatid
ON SS.productid = PRODUCTS.productid
INNER JOIN
EMPLOYEES ON SS.employeeid = EMPLOYEES.employeeid
WHERE
(PRODUCTS.productcatid <> '68')
AND (PRODUCTS.departmentid = '5')
AND (MEMBERS.status = 'A')
AND (SS.usedquantity < SS.initialquantity)
AND (PRODUCTS.scancode <> 'PASSCOMP1' OR
PRODUCTS.scancode <> 'PASSCOMP3' OR
PRODUCTS.scancode <> 'PASSCOMP5')
AND (PRODUCTS.inactive = 'False')
I really appreciate the help!!!
Sometnihg like this? Just add the fist query as table to your second query.
SELECT
SITES.sitename, MEMBERS.scancode,
MEMBERS.lname, MEMBERS.fname, MEMBERS.mtypeid,
MEMBERS.status, PRODUCTS.description, SS.initialdate,
SS.initialquantity, SS.usedquantity, SS.dateexpire,
EMPLOYEES.lname AS Expr1, EMPLOYEES.fname AS Expr2
FROM
SITES
INNER JOIN
MEMBERS ON SITES.siteid = MEMBERS.siteid
INNER JOIN
SS ON MEMBERS.memid = SS.memid
INNER JOIN
PRODUCTCATS
INNER JOIN
PRODUCTS ON PRODUCTCATS.productcatid = PRODUCTS.productcatid
ON SS.productid = PRODUCTS.productid
INNER JOIN
EMPLOYEES ON SS.employeeid = EMPLOYEES.employeeid
INNER JOIN
(SELECT
MEMBERS.memid
FROM
SITES
INNER JOIN
MEMBERS ON SITES.siteid = MEMBERS.siteid
INNER JOIN
SS ON MEMBERS.memid = SS.memid
INNER JOIN
PRODUCTCATS
INNER JOIN
PRODUCTS ON PRODUCTCATS.productcatid = PRODUCTS.productcatid
ON SS.productid = PRODUCTS.productid
INNER JOIN
EMPLOYEES ON SS.employeeid = EMPLOYEES.employeeid
WHERE
(PRODUCTS.productcatid = 77)
AND (SS.initialdate BETWEEN #rvPurchaseStart AND #rvPurchaseEnd)) TMP_TABLE ON MEMBERS.memid = TMP_TABLE.memid
WHERE
(PRODUCTS.productcatid <> '68')
AND (PRODUCTS.departmentid = '5')
AND (MEMBERS.status = 'A')
AND (SS.usedquantity < SS.initialquantity)
AND (PRODUCTS.scancode <> 'PASSCOMP1' OR PRODUCTS.scancode <> 'PASSCOMP3' OR PRODUCTS.scancode <> 'PASSCOMP5')
AND (PRODUCTS.inactive = 'False')

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

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
and 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.