Error Aggregations of aggregations are not allowed - sql

I'm wondering how to unbundle the AVG and SUM functions in this sample script to remove this error "Aggregations of aggregations are not allowed"
SELECT
a.id,
$DATEID_DATE(b.creation_date_id) AS creation_date,
AVG(CASE WHEN date_id BETWEEN b.creation_date_id AND b.creation_date_id + 6 THEN a.ros END),
AVG(CASE WHEN date_id BETWEEN b.creation_date_id AND b.creation_date_id + 6 THEN SAFE_DIVIDE(SUM(a.conv), SUM(a.cost)) END)
FROM a
INNER JOIN
b
ON b.id = a.id
GROUP BY 1,2

Related

Combine 2 queries together

I am struggling to work out combining a query that should give me 3 columns of Month, total_sold_products and drinks_sold_products
Query 1:
Select month(date), count(id) as total_sold_products
from Products
where date between '2022-01-01' and '2022-12-31'
Query 2
Select month(date), count(id) as drinks_sold_products
from Products where type = 'drinks' and date between '2022-01-01' and '2022-12-31'
I tried the union function but it summed count(id) twice and gave me only 2 columns
Many thanks!
Union is for attaching sets of data on top of each other. You need conditional aggregation or a join. See below.
SELECT MONTH(date),
COUNT(*) AS total_sold_products,
COUNT(CASE WHEN type = 'drinks' THEN 1 ELSE 0 END) AS drinks_sold_products,
FORMAT((CASE
WHEN COUNT(*) > 0 THEN
COUNT(CASE WHEN type = 'drinks' THEN 1 ELSE 0 END)/COUNT(*)
ELSE 0 END),
'P') AS Percentage
FROM Products
WHERE date BETWEEN'2022-01-01' AND '2022-12-31'
GROUP BY MONTH(date)

PLSQL same data with different dates from same table

I have a table in Oracle and I want to get difference of sums of debit and credit columns for sysdate and the same difference of sums of debit and credit columns from 6 months ago
My query is
select a.name,a.id, nvl(sum(a.debit),0)-nvl(sum(a.credit),0) current_bal
from mytable a
where a.id='1092' and a.docdate<=sysdate
group by a.name,a.id
union
select b.name,b.id,nvl(sum(b.debit),0)-nvl(sum(b.credit),0) current_bal1
from mytable b
where b. id='1092' and b.docdate<=add_months(sysdate,-6)
group by b.name,b.id;
I am getting the correct result but the query is returning two rows, where as my need is to show this result as a single row.
Any suggestions / correction in my query please.
You can use the conditional aggregation as follows:
select a.name,a.id, nvl(sum(CASE WHEN a.docdate<=sysdate THEN a.debit END),0)-nvl(sum(CASE WHEN a.docdate<=sysdate THEN a.credit END),0) current_bal,
nvl(sum(CASE WHEN b.docdate<=add_months(sysdate,-6) THEN a.debit END),0)-nvl(sum(CASE WHEN b.docdate<=add_months(sysdate,-6) THEN a.credit END),0) current_bal1
from mytable a
where a.id='1092'
group by a.name,a.id;
-- Update
If you are facing any issue then easiest way for you is to use the self join between sub-queries as follows:
SELECT A.NAME, A.ID, A.CURRENT_BAL, B.CURRENT_BAL1
FROM
(select a.name,a.id, nvl(sum(a.debit),0)-nvl(sum(a.credit),0) current_bal
from mytable a
where a.id='1092' and a.docdate<=sysdate
group by a.name,a.id) A
JOIN
(select b.name,b.id,nvl(sum(b.debit),0)-nvl(sum(b.credit),0) current_bal1
from mytable b
where b. id='1092' and b.docdate<=add_months(sysdate,-6)
group by b.name,b.id) B
ON A.ID = B.ID AND A.NAME = B.NAME;
You can use conditional aggregation:
select a.name, a.id,
coalesce(sum(a.debit), 0) - coalesce(sum(a.credit), 0) as current_bal,
(sum(case when a.docdate < add_months(sysdate, -6) then a.debit else 0 end) -
sum(case when a.docdate < add_months(sysdate, -6) then a.credit else 0 end)
) as bal_6_months
from mytable a
where a.id = '1092' and a.docdate <= sysdate
group by a.name, a.id;
This puts the two values in the same row. That seems more useful to me then having them in different rows.
Can you try:
select a.name,a.id, LISTAGG(nvl(sum(a.debit),0)-nvl(sum(a.credit),0), ' ') WITHIN GROUP (ORDER BY a.id) current_bal
from mytable a
where a.id='1092' and a.docdate<=sysdate
group by a.name,a.id
union
select b.name,b.id, LISTAGG(nvl(sum(a.debit),0)-nvl(sum(a.credit),0), ' ') WITHIN GROUP (ORDER BY a.id) current_bal
from mytable b
where b. id='1092' and b.docdate<=add_months(sysdate,-6)
group by b.name,b.id;

BigQuery: group counters by month after self-join

I have table that looks like this:
I'm trying to build a query, that will show specific partnerId counters groupped by keywordName and month.
To solve first part(without grouping by month), I've built this query:
SELECT keywordName, COUNT(keywordName) as total, IFNULL(b.ebay_count, 0) as ebay, IFNULL(c.amazon_count, 0) as amazon,
FROM LogFilesv2_Dataset.FR_Clickstats_v2 a
LEFT JOIN
(SELECT keywordName as kw , SUM(CASE WHEN partnerId='eBay' THEN 1 ELSE 0 END) as ebay_count
FROM LogFilesv2_Dataset.FR_Clickstats_v2
WHERE partnerId = 'eBay' GROUP BY kw) b
ON keywordName = b.kw
LEFT JOIN
(SELECT keywordName as kw , SUM(CASE WHEN partnerId='AmazonApi' THEN 1 ELSE 0 END) as amazon_count
FROM LogFilesv2_Dataset.FR_Clickstats_v2
WHERE partnerId = 'AmazonApi' GROUP BY kw) c
ON keywordName = c.kw
WHERE keywordName = 'flipper' -- just to filter out single kw.
GROUP BY keywordName, ebay, amazon
It works quite well and returns following output:
Now I'm trying to make additional group by month, but all my attempts returned incorrect results.
Final output supposed to be similar to this:
You can do this with conditional aggregation:
select
date_trunc(dt, month) dt,
keywordName,
count(*) total,
sum(case when partnerId = 'eBay' then 1 else 0 end) ebay,
sum(case when partnerId = 'AmazonApi' then 1 else 0 end) amazon
from LogFilesv2_Dataset.FR_Clickstats_v2
group by date_trun(dt, month), keywordName

Hive rolling sum of data over date

I am working on Hive and am facing an issue with rolling counts. The sample data I am working on is as shown below:
and the output I am expecting is as shown below:
I tried using the following query but it is not returning the rolling count:
select event_dt,status, count(distinct account) from
(select *, row_number() over (partition by account order by event_dt
desc)
as rnum from table.A
where event_dt between '2018-05-02' and '2018-05-04') x where rnum =1
group by event_dt, status;
Please help me with this if some one has solved a similar issue.
You seem to just want conditional aggregation:
select event_dt,
sum(case when status = 'Registered' then 1 else 0 end) as registered,
sum(case when status = 'active_acct' then 1 else 0 end) as active_acct,
sum(case when status = 'suspended' then 1 else 0 end) as suspended,
sum(case when status = 'reactive' then 1 else 0 end) as reactive
from table.A
group by event_dt
order by event_dt;
EDIT:
This is a tricky problem. The solution I've come up with does a cross-product of dates and users and then calculates the most recent status as of each date.
So:
select a.event_dt,
sum(case when aa.status = 'Registered' then 1 else 0 end) as registered,
sum(case when aa.status = 'active_acct' then 1 else 0 end) as active_acct,
sum(case when aa.status = 'suspended' then 1 else 0 end) as suspended,
sum(case when aa.status = 'reactive' then 1 else 0 end) as reactive
from (select d.event_dt, ac.account, a.status,
max(case when a.status is not null then a.timestamp end) over (partition by ac.account order by d.event_dt) as last_status_timestamp
from (select distinct event_dt from table.A) d cross join
(select distinct account from table.A) ac left join
(select a.*,
row_number() over (partition by account, event_dt order by timestamp desc) as seqnum
from table.A a
) a
on a.event_dt = d.event_dt and
a.account = ac.account and
a.seqnum = 1 -- get the last one on the date
) a left join
table.A aa
on aa.timestamp = a.last_status_timestamp and
aa.account = a.account
group by d.event_dt
order by d.event_dt;
What this is doing is creating a derived table with rows for all accounts and dates. This has the status on certain days, but not all days.
The cumulative max for last_status_timestamp calculates the most recent timestamp that has a valid status. This is then joined back to the table to get the status on that date. Voila! This is the status used for the conditional aggregation.
The cumulative max and join is a work-around because Hive does not (yet?) support the ignore nulls option in lag().

Subquery returned more than 1 value in MS SQL

In MS Sql.
SELECT a.SellerID,
SUM(TransactionFee) as TransactionFees,
SUM(Quantity*a.PriceItem) as TransactionValue,
COUNT(*) as OrdersWithTransactionFees,
SUM(Quantity) as Qty,
(SELECT SUM(a.Quantity*a.PriceItem) as WholeMonthTransactionValue
from BuyProductDetails where SellerID = a.SellerID) as aa
FROM BuyProductDetails as a
WHERE MONTH(a.OrderDate)=3
AND YEAR(a.OrderDate)=2013
AND TransactionFee IS NOT NULL
GROUP BY a.SellerID
I have the above query... it can't seems to be able to run.
Basically, I have this table BuyProductDetails which stores all the orders from different Sellers.
Some orders will have TransactionFee.
Now, what I need is to calculate the total sales of these orders with TransactionFee, and the total sales for these sellers including those orders without TransactionFee.
The result set should have the following fields:
SellerID
Sum of Transaction fee
Sum of total sales
Number of Orders with Transaction fee
Qty ordered
Total sales for that seller
But when I run this sql, it returns the following error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Any help is much appreciated. Thank you.
Tried something like this ?
SELECT a.SellerID,
SUM(TransactionFee) as TransactionFees,
SUM(Quantity*a.PriceItem) as TransactionValue,
COUNT(*) as OrdersWithTransactionFees,
SUM(Quantity) as Qty,
MIN(a.WholeMonthTransactionValue) as WholeMonthTransactionValue
FROM BuyProductDetails as a,
(SELECT b.SellerID,
SUM(b.Quantity*b.PriceItem) as WholeMonthTransactionValue,
MONTH(b.OrderDate),
YEAR(b.OrderDate)
FROM BuyProductDetails b
GROUP BY b.SellerID,
MONTH(b.OrderDate) as MonthID,
YEAR(b.OrderDate) as YearID) as aa
WHERE MONTH(a.OrderDate)=3
AND YEAR(a.OrderDate)=2013
AND TransactionFee IS NOT NULL
AND a.SellerID = aa.SellerID
AND MONTH(a.OrderDate)=aa.MonthID
AND YEAR(a.OrderDate) = aa.YearID
GROUP BY a.SellerID)
You can use more effective option with CASE expression
SELECT a.SellerID,
SUM(CASE WHEN TransactionFee IS NOT NULL THEN TransactionFee END) AS TransactionFees,
SUM(CASE WHEN TransactionFee IS NOT NULL THEN Quantity * PriceItem END) AS TransactionValue,
COUNT(CASE WHEN TransactionFee IS NOT NULL THEN 1 END) as OrdersWithTransactionFees,
SUM(CASE WHEN TransactionFee IS NOT NULL THEN Quantity END) as Qty,
SUM(Quantity * PriceItem) AS WholeMonthTransactionValue
FROM BuyProductDetails AS a
WHERE MONTH(a.OrderDate) = 3 AND YEAR(a.OrderDate) = 2013
GROUP BY a.SellerID
Demo on SQLFiddle
Or merely add correct alias in the subquery
SELECT a.SellerID,
SUM(TransactionFee) as TransactionFees,
SUM(Quantity*a.PriceItem) as TransactionValue,
COUNT(*) as OrdersWithTransactionFees,
SUM(Quantity) as Qty,
(SELECT SUM(d.Quantity * d.PriceItem)
FROM BuyProductDetails d
WHERE d.SellerID = a.SellerID) as WholeMonthTransactionValue
FROM BuyProductDetails as a
WHERE MONTH(a.OrderDate)=3
AND YEAR(a.OrderDate)=2013
AND TransactionFee IS NOT NULL
GROUP BY a.SellerID
Demo on SQLFiddle