Reputation: 25
I've been asked to start working more with data analysis and have ran into similar issues with SQL aggregate functions. Here's a very simplified dataset of sales transaction log and warehouse balance:
SALES
Item Period
A 2019
A 2019
A 2018
B 2019
WAREHOUSE
Item SerialN
A 111
A 123
A 222
C 321
I need to run SQL COUNT function on SALES table which is simple enough:
select count(a.Item), a.Item from SALES a
where a.period = 2019
group by a.Item
I also need to add the COUNT of items in WAREHOUSE table - also very straightforward on its own but not so much when trying to combine them into one query result.
select count(a.Item), a.Item, count(b.Item) from SALES a
left join WAREHOUSE b on a.Item = b.Item
where a.period = 2019
group by a.Item
The one above would mess up the result due to JOIN multiplying effect from WAREHOUSE table. What would be the best way to reach the result below? Is there a neat way to do this at all?
Item count_period current_warehouse
A 2 3
B 1
Upvotes: 2
Views: 7975
Reputation: 9083
First you need to group and filter data from the first table and then join with second table. Like this:
select A.item, A.count_period, count(W.item) current_warehouse
from (select S.item, max(S.Period) Period, count(S.Period) count_period
from SALES S
where S.Period = 2019
group by S.item) A
left join WAREHOUSE W on A.Item = W.Item
group by A.item, A.count_period;
One more way is:
select A.item, A.count_period, B.current_warehouse from
(select S.item, max(S.Period) Period, count(S.Period) count_period
from SALES S
where S.Period = 2019
group by S.item) A
left join
(select W.item, count(W.item) current_warehouse
from WAREHOUSE W
group by W.item) B
on A.item = B.item
or
select A.item, max(A.count_period), count(W.item) current_warehouse
from (select S.item, max(S.Period) Period, count(S.Period) count_period
from SALES S
where S.Period = 2019
group by S.item) A
left join WAREHOUSE W on A.Item = W.Item
group by A.item;
Here you have a DEMO where you can see all three are returning same data.
Upvotes: 1
Reputation: 107652
Consider joining two aggregate queries using Common Table Expressions (CTE):
WITH s_agg AS (
select s.Item, count(s.Item) as sales_count
from SALES s
where s.period = 2019
group by s.Item
),
w_agg as (
select w.Item, count(w.Item) as warehouse_count
from WAREHOUSE w
group by w.Item
)
SELECT s_agg.Item,
s_agg.sales_count,
w_agg.warehouse_count
FROM s_agg
LEFT JOIN w_agg
ON s_agg.Item = w_agg.Item
Upvotes: 1