Issue with performing an aggregate function on an expression containing an aggregate or a subquery - sql

select
A.ACCT as acct, COUNT(TRANS_key) as payments
from
DEBT A
join
TRANS B on B.DEBT_KEY = A.DEBT_KEY
join
TRANS_CODE C on C.TRANS_CODE = B.TRANS_CODE
join
CLIENT D on D.CLIENT_KEY = A.CLIENT_KEY
join
STATUS S on S.STAT_KEY = A. STAT_KEY
where
S.CATEGORY = 'A' and D.CLIENT_KEY = 43
Error:
Cannot perform an aggregate function on an expression containing an
aggregate or a subquery.
I am getting the error above when running this. I am not sure if I should be joining these tables differently or not, but I need this to be working.

All other selects have to be group by. Use this
select A.ACCT as acct, COUNT(TRANS_key) as payments
from DEBT A join TRANS B on B.DEBT_KEY = A.DEBT_KEY
join TRANS_CODE C on C.TRANS_CODE = B.TRANS_CODE
join CLIENT D on D.CLIENT_KEY = A.CLIENT_KEY
join STATUS S on S.STAT_KEY = A. STAT_KEY
where S.CATEGORY = 'A' and D.CLIENT_KEY = 43
GROUP BY A.ACCT

try
select A.ACCT as acct, COUNT(TRANS_key) as payments
from DEBT A
join TRANS B on B.DEBT_KEY = A.DEBT_KEY
join TRANS_CODE C on C.TRANS_CODE = B.TRANS_CODE
join CLIENT D on D.CLIENT_KEY = A.CLIENT_KEY
join STATUS S on S.STAT_KEY = A. STAT_KEY
where S.CATEGORY = 'A' and D.CLIENT_KEY = 43
group by A.ACCT
You can't use a aggregate function like count that return just 1 result and a select that returns multiple. If you want to the count for every a.acct then do the above.

Related

Oracle SQL How to Count Column Value Occurences and Group BY during joins

I'm working on another SQL query, trying to group a collection of records while doing a count and joining tables. See below for goal, current query, and attached scripts for building and populating tables.
Show all customers who have checked more books than DVDs. Display
customer name, total book checkouts and total DVD checkouts. Sort
results by customer first name and last name.
SELECT C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME, COUNT(T.TRANSACTION_ID)
FROM customer C
INNER JOIN library_card LC ON C.CUSTOMER_ID = LC.CUSTOMER_ID
INNER JOIN transaction T ON LC.LIBRARY_CARD_ID = T.LIBRARY_CARD_ID
INNER JOIN physical_item P ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
INNER JOIN catalog_item CT ON P.CATALOG_ITEM_ID = CT.CATALOG_ITEM_ID
GROUP BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME
ORDER BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME;
Run first: https://drive.google.com/open?id=1PYAZV4KIfZtxP4eQn35zsczySsxDM7ls
Run second: https://drive.google.com/open?id=1pAzWmJqvD3o3n6YJqVUM6TtxDafKGd3f
EDIT
With some help from Mr. Barbaros I've come up with the below query, which is closer. However, this query isn't returning any results for DVDs, which leads me to believe it's a join issue.
SELECT C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME, COUNT(CT1.TYPE) AS BOOK_COUNT, COUNT(CT2.TYPE) AS DVD_COUNT
FROM customer C
INNER JOIN library_card LC ON C.CUSTOMER_ID = LC.CUSTOMER_ID
INNER JOIN transaction T ON LC.LIBRARY_CARD_ID = T.LIBRARY_CARD_ID
INNER JOIN physical_item P ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
INNER JOIN catalog_item CT1 ON P.CATALOG_ITEM_ID = CT1.CATALOG_ITEM_ID AND CT1.TYPE = 'BOOK'
LEFT OUTER JOIN catalog_item CT2 ON P.CATALOG_ITEM_ID = CT2.CATALOG_ITEM_ID AND CT2.TYPE = 'DVD'
GROUP BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME, CT1.TYPE, CT2.TYPE
ORDER BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME;
Use "conditional aggregates" (use a case expression inside the aggregate function)
SELECT
C.CUSTOMER_FIRSTNAME
, C.CUSTOMER_LASTNAME
, COUNT( CASE WHEN CT.TYPE = 'BOOK' THEN T.TRANSACTION_ID END ) books
, COUNT( CASE WHEN CT.TYPE = 'DVD' THEN T.TRANSACTION_ID END ) dvds
FROM customer C
INNER JOIN library_card LC ON C.CUSTOMER_ID = LC.CUSTOMER_ID
INNER JOIN transaction T ON LC.LIBRARY_CARD_ID = T.LIBRARY_CARD_ID
INNER JOIN physical_item P ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
INNER JOIN catalog_item CT ON P.CATALOG_ITEM_ID = CT.CATALOG_ITEM_ID
GROUP BY
C.CUSTOMER_FIRSTNAME
, C.CUSTOMER_LASTNAME
HAVING
COUNT( CASE WHEN CT.TYPE = 'BOOK' THEN T.TRANSACTION_ID END )
> COUNT( CASE WHEN CT.TYPE = 'DVD' THEN T.TRANSACTION_ID END )
ORDER BY
C.CUSTOMER_FIRSTNAME
, C.CUSTOMER_LASTNAME
;
You can use catalog_item table twice( think of as seperate tables for books and dvds ), and compare by HAVING clause as :
SELECT C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME,
COUNT(CT1.CATALOG_ITEM_ID) as "Book Checkout",
COUNT(CT2.CATALOG_ITEM_ID) as "DVD Checkout"
FROM customer C
INNER JOIN library_card LC ON C.CUSTOMER_ID = LC.CUSTOMER_ID
INNER JOIN transaction T ON LC.LIBRARY_CARD_ID = T.LIBRARY_CARD_ID
INNER JOIN physical_item P ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
LEFT JOIN catalog_item CT1 ON P.CATALOG_ITEM_ID = CT1.CATALOG_ITEM_ID AND CT1.TYPE = 'BOOK'
LEFT JOIN catalog_item CT2 ON P.CATALOG_ITEM_ID = CT2.CATALOG_ITEM_ID AND CT1.TYPE = 'DVD'
GROUP BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME
HAVING COUNT(CT1.CATALOG_ITEM_ID) > COUNT(CT2.CATALOG_ITEM_ID)
ORDER BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME;
CUSTOMER_FIRSTNAME CUSTOMER_LASTNAME Book Checkout DVD Checkout
------------------ ----------------- ------------- -------------
Deena Pilgrim 3 1
Emile Cross 5 2
Please try to remove ,CT1.TYPE, CT2.TYPE on your group by clause.

A column in the predicate of the SQL

How can I select custType in the predicate section of the query
I can't do so now because
Error code -1, SQL state 42X04: Column 'CUSTTYPE' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE statement then 'CUSTTYPE' is not a column in the target table.
select p.SKU AS GiftID, p.ProductName AS GiftName,
case when sa.Sales >= v.LevelUpAmount then 1 else 2 end AS custType
from products p, campaign ca, SubCategory sc,
VIPLevelUpParam v,
ActiveParam a, customer c,
(select c.CustomerCode, sum(od.NetSales) AS Sales from customer c
INNER JOIN orders o ON (c.CustomerCode = o.CustomerCode)
INNER JOIN order_details od ON (o.OrderCode = od.OrderCode)
group by c.CustomerCode ) sa
where ca.CUSTOMERTYPE = custType AND
c.CustomerCode = 'CUS000001-2013-11-06' AND
p.SubCategoryID = sc.SubCategoryCode AND
p.SKU = ca.GiftID AND
sc.SubCategoryName = 'Gift'AND
v.LevelUpID = a.ActiveID AND
a.TableName = 'VIPLevelUpParam'
group by p.SKU, p.ProductName, sa.Sales, v.LevelUpAmount, custType;
Any one shed some light on this, it would be greatly appreciated!
As per logical query processing where clause is evaluated before select statement that why you're getting CustType column won't be available in where clause.
http://blog.sqlauthority.com/2009/04/06/sql-server-logical-query-processing-phases-order-of-statement-execution/
select * from
(
select p.SKU AS GiftID, p.ProductName AS GiftName,
case when sa.Sales >= v.LevelUpAmount then 1 else 2 end AS custType
from products p, campaign ca, SubCategory sc,
VIPLevelUpParam v,
ActiveParam a, customer c,
(select c.CustomerCode, sum(od.NetSales) AS Sales from customer c
INNER JOIN orders o ON (c.CustomerCode = o.CustomerCode)
INNER JOIN order_details od ON (o.OrderCode = od.OrderCode)
group by c.CustomerCode ) sa
) DT
where DT.CUSTOMERTYPE = DT.custType AND
DT.CustomerCode = 'CUS000001-2013-11-06' AND
DT.SubCategoryID = DT.SubCategoryCode AND
DT.SKU = DT.GiftID AND
DT.SubCategoryName = 'Gift' AND
DT.LevelUpID = DT.ActiveID AND
DT.TableName = 'VIPLevelUpParam'
group by DT.SKU, DT.ProductName, DT.Sales, DT.LevelUpAmount, DT.custType;

Using a sum with a distinct in SQL

I have a query that returns the data i'm looking for using a distinct, but when I SUM that data I get a wrong amount for a my hierachy point '4-2-0-0-5-2'. 4-2-0-0-5-2 has multiple rows so when I sum it, it doesn't add up correctly. What would be the best way to incorporate a distinct into a SUM statement. Any help would be appreicated. Thanks.
First query :
Select distinct B.Proj_Nbr,c.proj_cc,h.proj_cc, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per, A.Amount
from acct_bal a
inner join dim_proj b on a.dim_proj_id = b.dim_proj_id
inner join essbase_fcs.projects_hier_map c on c.proj_nbr = b.proj_nbr
inner join dim_per_mo d on d.dim_per_mo_id = a.dim_per_mo_id
Inner Join Dim_Acct F On A.Dim_Acct_Id = F.Dim_Acct_Id
Inner Join Dim_Org G On A.Dim_Org_Id = G.Dim_Org_Id
inner join essbase_fcs.projects_hier_map h on h.proj_cc = g.cost_ctr
inner join dim_org g1 on c.proj_cc = g1.cost_ctr
Where F.Fin_Lee_Nbr = 500
and c.proj_hier like '4-2-0-0-5-2%'
And A.Dim_Scnro_Id = '45'
And D.Fscl_Yr = '2014'
And b.Proj_Nbr = '9005459'
and fscl_per ='1'
RESULT of 2 rows:
9005459 0358080 0358080 4-2-0-0-5-2 Global Sales.com (iSell) 179777.09
9005459 0358080 0358057 4-2-0-0-5-5 Global Sales.com (iSell) 2257.3**
When I want to sum the data I use this query below. This gives me the two rows i'm looking for, but proj_hier 4-2-0-0-5-2 has the wrong amount because it has multiple rows.
Select B.Proj_Nbr,c.proj_cc, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per, sum(A.Amount)
from acct_bal a
inner join dim_proj b on a.dim_proj_id = b.dim_proj_id
inner join essbase_fcs.projects_hier_map c on c.proj_nbr = b.proj_nbr
inner join dim_per_mo d on d.dim_per_mo_id = a.dim_per_mo_id
Inner Join Dim_Acct F On A.Dim_Acct_Id = F.Dim_Acct_Id
Inner Join Dim_Org G On A.Dim_Org_Id = G.Dim_Org_Id
inner join essbase_fcs.projects_hier_map h on h.proj_cc = g.cost_ctr
inner join dim_org g1 on c.proj_cc = g1.cost_ctr
Where F.Fin_Lee_Nbr = 500
and c.proj_hier like '4-2-0-0-5-2%'
And A.Dim_Scnro_Id = '45'
And D.Fscl_Yr = '2014'
And b.Proj_Nbr = '9005459'
and fscl_per ='1'
group by B.Proj_Nbr,c.proj_cc,f.dim_acct_id, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per
having Sum(A.Amount) <> 0
Order By H.Proj_Hier, B.Proj_Nbr, D.Fscl_Per
Please Generalize the Question and then ask, If i understood your problem Here is solution:
General Query :
select sum(a.amountColumn) from your_table
group by agrrColumnName;
If i change your query :
Select distinct B.Proj_Nbr,c.proj_cc,h.proj_cc, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per, sum(A.Amount)
from acct_bal a
inner join dim_proj b on a.dim_proj_id = b.dim_proj_id
inner join essbase_fcs.projects_hier_map c on c.proj_nbr = b.proj_nbr
inner join dim_per_mo d on d.dim_per_mo_id = a.dim_per_mo_id
Inner Join Dim_Acct F On A.Dim_Acct_Id = F.Dim_Acct_Id
Inner Join Dim_Org G On A.Dim_Org_Id = G.Dim_Org_Id
inner join essbase_fcs.projects_hier_map h on h.proj_cc = g.cost_ctr
inner join dim_org g1 on c.proj_cc = g1.cost_ctr
Where F.Fin_Lee_Nbr = 500
and c.proj_hier like '4-2-0-0-5-2%'
And A.Dim_Scnro_Id = '45'
And D.Fscl_Yr = '2014'
And b.Proj_Nbr = '9005459'
and fscl_per ='1' group by B.Proj_Nbr;

SQL Counting # of times a member shows up with certain code values

I am running a query that returns the location of a member and the product the member is enrolled in. Each time a member makes a claim with their product, they get a revenue code associated to them. Below is my query that I have now:
SELECT DISTINCT
e.State,
f.Product,
d.MemberID,
b.RevenueCode
FROM
Claims a
INNER JOIN
dw.Revenue b
ON
a.RevenueKey = b.RevenueKey
INNER JOIN
dw.Member d
ON
a.MemberKey = d.MemberKey
INNER JOIN
dw.Product f
ON
a.ProductKey = f.ProductKey
INNER JOIN
dw.State
ON
a.StateKey = f.StateKey
WHERE
b.RevenueCode IN ('0134', '0135')
It returns a set like the following:
State Product MemberID RevenueCode
MN xxx 945-234-245 0134
MN xxx 945-234-245 0135
SD xxx 231-345-235 0134
When a MemberID has both 0134 and 0135 RevenueCodes associated with it, they are considered to be in a special category. How would I modify my above query to count the number of times a MemberID has both RevenueCodes by State and by Product?
SELECT DISTINCT
e.State
,f.Product
,d.MemberID
,b.RevenueCode
,(SELECT 1
FROM Claims AS a1
INNER JOIN dw.Revenue AS b1 ON a1.RevenueKey = b1.RevenueKey
WHERE b1.RevenueCode IN ('0134', '0135')
AND b.revenuekey = b1.revenuekey
AND a.MemberKey = a1.Memberkey
HAVING COUNT(DISTINCT b1.RevenueCode) = 2) AS SpecialCategory
FROM Claims a
INNER JOIN dw.Revenue b ON a.RevenueKey = b.RevenueKey
INNER JOIN dw.Member d ON a.MemberKey = d.MemberKey
INNER JOIN dw.Product f ON a.ProductKey = f.ProductKey
INNER JOIN dw.State ON a.StateKey = f.StateKey
WHERE b.RevenueCode IN ('0134', '0135')
SELECT DISTINCT
e.State,
f.Product,
d.MemberID,
b.RevenueCode.
CASE WHEN EXISTS(
SELECT NULL
FROM Claims a1
JOIN dw.Revenue b1 ON a1.RevenueKey = b1.RevenueKey
JOIN dw.Member d1 ON a1.MemberKey = d1.MemberKey
JOIN dw.Product f1 ON a1.ProductKey = f1.ProductKey
WHERE b1.RevenueCode IN('0134', '0135') AND
d1.MemberID = d.MemberID AND
f1.ProductKey = f.ProductKey AND
f1.StateKey = f.StateKey
) THEN 1 ELSE 0 END As IsSpecialCategory
FROM
...
Figured it out...Simply needed to Count the Distinct RevenueCodes and Group By State, Product, and MemberID

how to check if a type of row exists in a table

Hi I have an order table and a payment table which are linked by order_num. I would like to get entries from order table who have entries in the payment table of PaymentType 'A' as well as PaymentType 'B' and their amounts match. Example order number 411 should only be returned to me if it has at least two payments and one of them is paymenttype 'A' and the other one is paymenttype 'b' and amount for both is 45
Thanks.
Like the comments state, there is very little info to go off of for a truly definitive answer. Here goes a possible solution, at least in a basic form.
SELECT *
FROM Orders o
LEFT JOIN Payment p1 ON o.order_num = p1.order_num
LEFT JOIN Payment p2 ON o.order_num = p2.order_num
WHERE p1.Type = "A"
AND p2.Type = "B"
AND p1.Amount = p2.Amount
As long as you can guarantee that there are at most one A and one B row:
SELECT
<columns here>
FROM
Orders O
INNER JOIN Payments PA ON
PA.order_number = O.order_number AND
PA.payment_type = 'A'
INNER JOIN Payments PB ON
PB.order_number = O.order_number AND
PB.payment_type = 'B'
WHERE
PA.amount = PB.amount
How about this:
SELECT o.OrderID,
o.Amount
FROM Order AS o
INNER JOIN Payment AS pA ON pA.OrderID = o.OrderID AND pA.PaymentType = 'A'
INNER JOIN Payment AS pB ON pB.OrderID = o.OrderID AND pB.PaymentType = 'B'
WHERE pA.Amount = pB.Amount
GROUP BY o.OrderID,
o.Amount
Making some (hopefully) reasonable assumptions about the names of tables, columns, etc, how about...
SELECT *
FROM ORDER_TABLE
WHERE EXISTS (SELECT *
FROM PAYMENT_TABLE
WHERE PAYMENT_TYPE = 'A' AND
PAYMENT_TABLE.ORDER = ORDER_TABLE.ORDER AND
PAYMENT_TABLE.AMOUNT = ORDER_TABLE.AMOUNT) AND
EXISTS (SELECT *
FROM PAYMENT_TABLE
WHERE PAYMENT_TYPE = 'B' AND
PAYMENT_TABLE.ORDER = ORDER_TABLE.ORDER AND
PAYMENT_TABLE.AMOUNT = ORDER_TABLE.AMOUNT);
Assumes amounts exist only in the payment table, and that the payment table may have multiple records for a payment type.
select [columns]
from ORDER O
where exists (select null from PAYMENT PA, PAYMENT PB
where PA.PAYMENT_TYPE = 'A'
and PB.PAYMENT_TYPE = 'B'
and PA.ORDER_NUM = O.ORDER_NUM
and PB.ORDER_NUM = O.ORDER_NUM
and PA.AMOUNT = PB.AMOUNT)