Using subquery to find sum for individuals for reporting - sql

I'm trying to calculate the sum of unposted transactions for individuals. I'm thinking I need a subquery to do this but I receive the
error (Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.)
I should have known that I would get that error but I'm not sure how to tie in the table. Here's the full query:
select ar.id_num,
nm.last_name,
nm.first_name,
am.ADDR_LINE_1,
am.ADDR_LINE_2,
am.CITY,
am.STATE,
am.ZIP,
nm.EMAIL_ADDRESS,
ar.ar_bal_to_dte,
ar.UNAPPLIED_FIN_AID,
lt.Last_term_end_date
,ar.ar_bal_to_dte + ar.UNAPPLIED_FIN_AID as 'Unapplied Aid',
case when getdate()<= arm.end_dte then 'Dir Deposit' else 'Check' end as 'pmt type',
'Unposted Charges' = (select SUM (trans_amt) from TRANS_HIST where SOURCE_CDE = '#C' AND SUBSID_CDE = 'AR' group by ID_NUM )
from SUBSID_MASTER ar left outer join ccsc_last_term_end_date_v lt on ar.ID_NUM = lt.id_num
left outer join SUBSID_MASTER_EPAY_ACCT arm ON AR.ID_NUM = arm.ID_NUM
inner join TRANS_HIST th ON AR.ID_NUM = th.ID_NUM
JOIN NAME_MASTER nm ON ar.ID_NUM = nm.ID_NUM
JOIN ADDRESS_MASTER am on ar.ID_NUM = am.ID_NUM
where ar.SUBSID_CDE = 'AR'
and ar.AR_BAL_TO_DTE < 0 and am.ADDR_CDE = '*LHP'
order by lt.Last_term_end_date
Does anyone have some advice for me? It would be greatly appreciated.

This is the only subquery in the query:
'Unposted Charges' = (select SUM(trans_amt) from TRANS_HIST where SOURCE_CDE = '#C' AND SUBSID_CDE = 'AR' group by ID_NUM )
First, this looks really awkward. Only use single quotes for string and date constants. Use square braces:
[Unposted Charges] = (select SUM(trans_amt) from TRANS_HIST where SOURCE_CDE = '#C' AND SUBSID_CDE = 'AR' group by ID_NUM )
The problem is the GROUP BY. It returns a different row for each ID_NUM, hence the error.
One easy fix to the syntax problem is:
[Unposted Charges] = (select SUM(trans_amt) from TRANS_HIST where SOURCE_CDE = '#C' AND SUBSID_CDE = 'AR')
However, you probably intend:
[Unposted Charges] = (select SUM(th.trans_amt)
from TRANS_HIST th
where th.SOURCE_CDE = '#C' AND
th.SUBSID_CDE = 'AR' AND
th.ID_NUM = ar.ID_NUM
)

A nice alternative to the subselect would be to join to a derived table of
... INNER JOIN (SELECT TH.ID_NUM, SUM(TH.TRANS_AMT) AS UNPOSTED_CHARGES FROM TRANS_HIST TH WHERE TH.SOURCE_ID = '#C' AND TH.SUBSID_CDE = 'AR' GROUP BY TH.ID_NUM) DT ON DT.ID_NUM = AR.ID_NUM ...
So then you can just use DT.UNPOSTED_CHARGES in your select list.

Related

SQL count(*) with having

I have this query on oracle.
SELECT CBG.refs, CBG.cuo, CBG.date, CBG.nber, CG.date, CBG.conso,
(SELECT COUNT(*)
FROM MAD.VIN CBV
WHERE CBV.CUO = CBG.CUO AND
CBV.NBER = CBG.NBER AND
CBV.DATE = CBG.DATE AND
CBV.REFS = CBG.REFS
GROUP BY CUO , DATE , NBER , REFS ) AS COUNTS ,
CBG.CONSO_CONCESS AS CONCESS
FROM MAD.GEN CBG, MAD.CAR_GEN CG
WHERE CBG.cuo = CG.cuo AND
CBG.CONSO_DATE IS NOT NULL AND
CBG.date = CG.date AND
CBG.nber = CG.nber
HAVING COUNTS > 0;
when i run this sql query it gives me an error that says: invalid identifier counts.
How do we get results only if count is greater than a given parameter?
Thanks.
Unlike in MySQL, in Oracle we cannot refer to an alias in the HAVING clause (aliases can only be referenced in the ORDER BY clause). One workaround would be to put your current logic into a CTE and then filter it.
WITH cte AS (
SELECT CBG.refs, CBG.cuo, CBG.date AS cbg_date, CBG.nber, CG.date AS cg_date,
CBG.conso,
(SELECT COUNT(*)
FROM MAD.VIN CBV
WHERE CBV.CUO = CBG.CUO AND
CBV.NBER = CBG.NBER AND
CBV.DATE = CBG.DATE AND
CBV.REFS = CBG.REFS
GROUP BY CUO, DATE, NBER, REFS) AS COUNTS,
CBG.CONSO_CONCESS AS CONCESS
FROM MAD.GEN CBG
INNER JOIN MAD.CAR_GEN CG
ON CBG.cuo = CG.cuo AND
CBG.date = CG.date AND
CBG.nber = CG.nber
WHERE CBG.CONSO_DATE IS NOT NULL
)
SELECT refs, cuo, cbg_date, nber, cg_date, conso, COUNTS, CONCESS
FROM cte
WHERE COUNTS > 0;

Query on subquery containing JOINS in Salesforce SQL (SOQL)

SELECT
Email_address, COUNT(Order_date)
FROM
(SELECT
cust.Email_address, COUNT(ol.Variant_name), ord.Order_date
FROM
DMW_Order_Line_v3 ol
JOIN
DMW_Order_v3 ord ON ol.Unique_transaction_identifier = ord.Unique_transaction_identifier
AND ol.Brand_country = ord.Brand_country
JOIN
DMW_Customer_v3 cust ON ord.Email_address = cust.Email_address
AND ord.Brand_country = cust.Brand_country
WHERE
ord.Brand_country = 'kiehls-emea_CZ'
AND cust.Address_country = 'CZ'
AND cust.Optin_email != 'False'
AND ol.Line_status = 'SHIPPED'
AND ol.Variant_name = 'Sample'
GROUP BY
cust.Email_address, ord.Order_date
HAVING
COUNT(ol.Variant_name) >= 4)
GROUP BY
Email_address
Please, forgive me that I'm posting the whole body of the code. But it might be helpful somehow, who knows. As you can see it is a query on subquery containing joins. I'm using Salesforce SQL. When I run the code, I get this error:
Error saving the query field. Incorrect syntax near the keyword 'GROUP'.
What am I doing wrong? Besides being a noob ;-)
You don't need the count column in the subquery:
SELECT Email_address, COUNT(*)
FROM (SELECT cust.Email_address, ord.Order_date
FROM DMW_Order_Line_v3 ol JOIN
DMW_Order_v3 ord
ON ol.Unique_transaction_identifier = ord.Unique_transaction_identifier AND
ol.Brand_country = ord.Brand_country JOIN
DMW_Customer_v3 cust
ON ord.Email_address = cust.Email_address AND
ord.Brand_country = cust.Brand_country
WHERE ord.Brand_country = 'kiehls-emea_CZ' AND
cust.Address_country = 'CZ' AND
cust.Optin_email <> 'False' AND
ol.Line_status = 'SHIPPED' AND
ol.Variant_name = 'Sample'
GROUP BY cust.Email_address, ord.Order_date
HAVING COUNT(ol.Variant_name) >= 4
) e
GROUP BY Email_Address

Case Statement within in Statement in MS SQL

I want to compare two different tables in IN statement based on condition.
SELECT DISTINCT
cts.ContactType
,ISNULL(ctl.[Description], CONCAT('Unknown Contact Type: ',cts.ContactType)) AS [Description]
FROM
( SELECT Null AS [ContactType]
WHERE ISNULL(Null, '') <> ''
UNION ALL
SELECT DISTINCT cta.ContactType
FROM
(SELECT u.AccessUserID
FROM v2010_vUsers u
WHERE u.UserID = 'harry_1#cared_t'
UNION ALL
SELECT ur.AccessUserID
FROM v2010_UserRoles ur
WHERE ur.UserID = 'harry_1#cared_t') r --Roles user has
INNER JOIN v2010_UDV_ContactType_AccessMatrix_Full cta --ContactTypes Accessible
ON cta.AccessUserID = r.AccessUserID) cts --ContactTypes Selectable
LEFT JOIN v2010_ListEntries ctl --ContactType List
ON ctl.ListId='CONTACTTYPE' and ctl.Code = cts.ContactType
WHERE cts.ContactType In
(
CASE WHEN (SELECT dbo.f2010_IsFeatureAllowedInTenancy('ContactTypeSC', dbo.f2010_PartnerDivisionID('06b30841-2496-48ef-b91a-21f06a9299f2'))) = '1'
THEN (SELECT Code From v2010_ListEntries WHERE ListId='CONTACTTYPESC')
ELSE (SELECT Code From v2010_ListEntries WHERE ListId='CONTACTTYPE')
END
)
ERROR : Subquery returned more than 1 value. This is not permitted
when the subquery follows =, !=, <, <= , >, >= or when the subquery is
used as an expression.
Error is in following lines:
WHERE cts.ContactType In
(
CASE WHEN (SELECT dbo.f2010_IsFeatureAllowedInTenancy('ContactTypeSC', dbo.f2010_PartnerDivisionID('06b30841-2496-48ef-b91a-21f06a9299f2'))) = '1'
THEN (SELECT Code From v2010_ListEntries WHERE ListId='CONTACTTYPESC')
ELSE (SELECT Code From v2010_ListEntries WHERE ListId='CONTACTTYPE')
END
)
I am not able to use case when in IN statement. if I write WHERE cts.ContactType In (SELECT Code From v2010_ListEntries WHERE ListId='CONTACTTYPESC') it is working but I want to compare condition and based on condition compare table.
It is a bit hard to tell where the multiple rows problem is coming from, but I am thinking:
WHERE (dbo.f2010_IsFeatureAllowedInTenancy('ContactTypeSC', dbo.f2010_PartnerDivisionID('06b30841-2496-48ef-b91a-21f06a9299f2')) = '1' and
cts.ContactType In (SELECT Code From v2010_ListEntries WHERE ListId = 'CONTACTTYPESC')
) OR
(dbo.f2010_IsFeatureAllowedInTenancy('ContactTypeSC', dbo.f2010_PartnerDivisionID('06b30841-2496-48ef-b91a-21f06a9299f2')) <> '1' and
cts.ContactType In (SELECT Code From v2010_ListEntries WHERE ListId = 'CONTACTTYPE'')
)
Or, more simply as:
cts.ContactType In (SELECT le.Code
FROM v2010_ListEntries le CROSS JOIN
(VALUES (CASE WHEN dbo.f2010_IsFeatureAllowedInTenancy('ContactTypeSC', dbo.f2010_PartnerDivisionID('06b30841-2496-48ef-b91a-21f06a9299f2')) THEN 'CONTACTTYPESC' ELSE 'CONTACTTYPESC' END)) v(listId)
WHERE le.ListId = v.ListId
)

Progress SQL Column cannot be found or is not specified for query

I'm writing SQL against a Progress 10.2B07 database and am getting the following error "Column 'OUTERINVOICEHEADER.MEMBERID' cannot be found or is not specified for query (13865).
Here is the query:
select concat(substring(OuterInvoiceHeader.sold_to_cust_nbr, 1, 6) + '-', OuterInvoiceHeader.sold_to_cust_seq) as MemberID,
sum(OuterInvoiceHeader.net_weight) as TotalInvoicePounds,
sum(OuterInvoiceHeader.net_weight / 2000) as TotalTons,
sum(OuterInvoiceHeader.invoice_amt) as InvoiceAmount,
sum(InvoiceSurcharges.Surcharge) as Surcharges,
sum(OuterInvoiceHeader.invoice_amt - InvoiceSurcharges.Surcharge) as Total,
sum(Returns.qty_received) as PoundsReturned
from AXS.PUB.ivc_header OuterInvoiceHeader
inner join
(select m.invoice_nbr, sum(m.extension) Surcharge from AXS.PUB.ivc_mchgs m
inner join
AXS.PUB.ivc_header h
on h.invoice_nbr = m.invoice_nbr
group by m.invoice_nbr) InvoiceSurcharges
on OuterInvoiceHeader.invoice_nbr = InvoiceSurcharges.invoice_nbr
left outer join
(select concat(substring(ReturnHeader.ship_to_nbr, 1, 6)+'-',InnerInvoiceHeader.sold_to_cust_seq) as ReturnMemberID,
ReturnHeader.invoice_nbr as ReturnInvoiceNum,
qty_received
from AXS.PUB.return_hdr ReturnHeader
inner join
AXS.PUB.ivc_header InnerInvoiceHeader
on ReturnHeader.invoice_nbr = InnerInvoiceHeader.invoice_nbr
inner join AXS.PUB.return_line ReturnLine
on ReturnHeader.claim_nbr = ReturnLine.claim_nbr
where ReturnInvoiceNum = '0001010914'
group by ReturnMemberID, ReturnInvoiceNum, qty_received) Returns
on OuterInvoiceHeader.MemberID = Returns.ReturnMemberID
--on OuterInvoiceHeader.invoice_nbr = Returns.ReturnInvoiceNum
where OuterInvoiceHeader.sold_to_cust_nbr = '000837' and OuterInvoiceHeader.invoice_date between '06/01/2016' and '06/30/2016' and OuterInvoiceHeader.invoice_status = '5804' and OuterInvoiceHeader.invoice_type='5601'
group by MemberID
The problem is in the left join; the commented out on clause "on OuterInvoiceHeader.invoice_nbr = Returns.ReturnInvoiceNum" will work if uncommented. The "on OuterInvoiceHeader.MemberID = Returns.ReturnMemberID" clause gives me the error.
What I don't understand is that both of these reference a column in the top SELECT statement, the only difference is that one is a concatenation and the other is not.
I hope that I just can't see the forest for the trees here and the answer is simple, so if anyone has any suggestions or questions I'm all ears.
try this:
I replaced the references to the alias MemberID to be the actual concatinated columns CONCAT(SUBSTRING(OuterInvoiceHeader.sold_to_cust_nbr, 1, 6)+'-', OuterInvoiceHeader.sold_to_cust_seq)
SELECT CONCAT(SUBSTRING(OuterInvoiceHeader.sold_to_cust_nbr, 1, 6)+'-', OuterInvoiceHeader.sold_to_cust_seq) AS MemberID
, SUM(OuterInvoiceHeader.net_weight) AS TotalInvoicePounds
, SUM(OuterInvoiceHeader.net_weight / 2000) AS TotalTons
, SUM(OuterInvoiceHeader.invoice_amt) AS InvoiceAmount
, SUM(InvoiceSurcharges.Surcharge) AS Surcharges
, SUM(OuterInvoiceHeader.invoice_amt - InvoiceSurcharges.Surcharge) AS Total
, SUM(Returns.qty_received) AS PoundsReturned
FROM AXS.PUB.ivc_header OuterInvoiceHeader
INNER JOIN
(SELECT m.invoice_nbr
, SUM(m.extension) Surcharge
FROM AXS.PUB.ivc_mchgs m
INNER JOIN AXS.PUB.ivc_header h ON h.invoice_nbr = m.invoice_nbr
GROUP BY m.invoice_nbr) InvoiceSurcharges ON OuterInvoiceHeader.invoice_nbr = InvoiceSurcharges.invoice_nbr
LEFT OUTER JOIN
(SELECT CONCAT(SUBSTRING(ReturnHeader.ship_to_nbr, 1, 6)+'-', InnerInvoiceHeader.sold_to_cust_seq) AS ReturnMemberID
, ReturnHeader.invoice_nbr AS ReturnInvoiceNum
, qty_received
FROM AXS.PUB.return_hdr ReturnHeader
INNER JOIN AXS.PUB.ivc_header InnerInvoiceHeader ON ReturnHeader.invoice_nbr = InnerInvoiceHeader.invoice_nbr
INNER JOIN AXS.PUB.return_line ReturnLine ON ReturnHeader.claim_nbr = ReturnLine.claim_nbr
WHERE ReturnInvoiceNum = '0001010914'
GROUP BY ReturnMemberID
, ReturnInvoiceNum
, qty_received) Returns ON CONCAT(SUBSTRING(OuterInvoiceHeader.sold_to_cust_nbr, 1, 6)+'-', OuterInvoiceHeader.sold_to_cust_seq) = Returns.ReturnMemberID
--on OuterInvoiceHeader.invoice_nbr = Returns.ReturnInvoiceNum
WHERE OuterInvoiceHeader.sold_to_cust_nbr = '000837'
AND OuterInvoiceHeader.invoice_date BETWEEN '06/01/2016' AND '06/30/2016'
AND OuterInvoiceHeader.invoice_status = '5804'
AND OuterInvoiceHeader.invoice_type = '5601'
GROUP BY CONCAT(SUBSTRING(OuterInvoiceHeader.sold_to_cust_nbr, 1, 6)+'-', OuterInvoiceHeader.sold_to_cust_seq);
Basically you need to keep in mind the order which SQL statements are executed:
FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause
That's a computed column alias and thus the error. You should consider using the entire expression rather like
on concat(substring(OuterInvoiceHeader.sold_to_cust_nbr, 1, 6) + '-', OuterInvoiceHeader.sold_to_cust_seq) = Returns.ReturnMemberID
Instead of on OuterInvoiceHeader.MemberID = Returns.ReturnMemberID. As well, change any other place where you are using the same alias. You can and should use that alias only in a outer query and not in the same query.

Updating Table with multiple values

When I run this code
UPDATE #YesterdayAssignments
SET ThisWeek = (
SELECT COUNT(*)
FROM #YesterdayAssignments U
INNER JOIN vstudyassignments A
ON U.HHID = A.lhouseholdid
INNER JOIN tstudies S
ON S.lstudyid = A.lstudyid
WHERE S.lstudytypeid IN (0,1,2)
AND S.bafteruse <> 1
AND S.lstatusid = 1
AND (A.dmailingdate BETWEEN DATEADD(DAY,1-DATEPART(dw,GETDATE()),GETDATE()) AND GETDATE()
OR A.dPulledDate BETWEEN DATEADD(DAY,1-DATEPART(dw,GETDATE()),GETDATE()) AND GETDATE())
AND S.dMailingDate < GETDATE()
GROUP BY HHID
)
FROM #YesterdayAssignments U
INNER JOIN vstudyassignments A
ON U.HHID = A.lhouseholdid
INNER JOIN tstudies S
ON S.lstudyid = A.lstudyid
WHERE S.lstudytypeid IN (0,1,2)
AND S.bafteruse <> 1
AND S.lstatusid = 1
AND (A.dmailingdate BETWEEN DATEADD(DAY,1-DATEPART(dw,GETDATE()),GETDATE()) AND GETDATE()
OR A.dPulledDate BETWEEN DATEADD(DAY,1-DATEPART(dw,GETDATE()),GETDATE()) AND GETDATE())
AND S.dMailingDate < GETDATE()
AND HHID = U.HHID
I get the error;
Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated.
I need to update a table with multiple values. Any ideas?
I don't think the query is doing what you think. Try this (freehand):
WITH data (Total, HHID) AS
(
SELECT COUNT(*),
HHID
FROM #YesterdayAssignments U
INNER JOIN vstudyassignments A ON U.HHID = A.lhouseholdid
INNER JOIN tstudies S ON S.lstudyid = A.lstudyid
WHERE S.lstudytypeid IN (0,1,2)
AND S.bafteruse <> 1
AND S.lstatusid = 1
AND (A.dmailingdate BETWEEN DATEADD(DAY,1-DATEPART(dw,GETDATE()),GETDATE()) AND GETDATE()
OR A.dPulledDate BETWEEN DATEADD(DAY,1-DATEPART(dw,GETDATE()),GETDATE()) AND GETDATE())
AND S.dMailingDate < GETDATE()
GROUP BY HHID
)
UPDATE U
SET ThisWeek = Total
FROM #YesterdayAssignments U
INNER JOIN data D ON D.HHID = U.HHID;
The way you have it, you are grouping on HHID which potential returns multiple counts (when there is more than one HHID). So in effect, you are trying to do: ThisWeek = val1, val2, ..., valN.