Why is SUM() and COUNT() returning different values? - sql

I have two near identical queries and I'm trying to understand why they're returning different results. I would like to produce a table with a user_id and a food_orders column showing how many items each user has ordered. These queries produce this table but calculate different results in the food_orders column in some rows.
My questions are why is this and which should I use?
A simplified version of my queries are below.
Query 1 (using COUNT):
WITH order_made AS (
SELECT restaurant_id,
count(
CASE
WHEN item LIKE '%_angus' then 1
WHEN item LIKE '%_organic' then 1
WHEN item LIKE '%_lean' then 1
ELSE 0
END)
AS burgers
FROM mcdonalds.specialist_orders
GROUP BY mcdonalds.specialist_orders.user_id
UNION ALL
SELECT restaurant_id,
COUNT(
CASE
WHEN item LIKE 'salad%' THEN 1
WHEN item LIKE 'tomato%' THEN 1
WHEN item LIKE 'potatoes%' THEN 1
ELSE 0
END)
AS vegetables
FROM public.bulk_orders
GROUP BY public.bulk_orders.user_id),
Query 2 (using SUM):
WITH orders_made AS (
SELECT user_id, SUM(food_orders) AS food_orders
FROM (SELECT user_id,
CASE
WHEN item LIKE '%_angus' then 1
WHEN item LIKE '%_organic' then 1
WHEN item LIKE '%_lean' then 1
ELSE 0
END
AS food_orders
FROM mcdonalds.specialist_orders
UNION ALL
SELECT user_id,
CASE
WHEN item LIKE 'salad%' THEN 1
WHEN item LIKE 'tomato%' THEN 1
WHEN item LIKE 'potatoes%' THEN 1
ELSE 0
END
AS food_orders
FROM public.bulk_orders
GROUP BY user_id)

Because COUNT function count when the value isn't NULL (include 0) if you don't want to count, need to let CASE WHEN return NULL
so if you remove ELSE 0 from your CASE WHEN or use ELSE NULL to instead, that result would be as same as SUM
WITH order_made AS (
SELECT restaurant_id,
count(
CASE
WHEN item LIKE '%_angus' then 1
WHEN item LIKE '%_organic' then 1
WHEN item LIKE '%_lean' then 1
END)
AS burgers
FROM mcdonalds.specialist_orders
GROUP BY mcdonalds.specialist_orders.user_id
UNION ALL
SELECT restaurant_id,
COUNT(
CASE
WHEN item LIKE 'salad%' THEN 1
WHEN item LIKE 'tomato%' THEN 1
WHEN item LIKE 'potatoes%' THEN 1
END)
AS vegetables
FROM public.bulk_orders
GROUP BY public.bulk_orders.user_id),

Related

Is there a way to collect the data and inspect in one pass using groupby function

Sample Data of table_1
Have this Query that returns
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0 END) AS num_activity_a_or_b
from table_1
group by customer
Results:
Want to extend this to return one more column if for a given code say X1 if the Activity is "a" and "c" then return num_of_a_and_c_activity.
A bit stuck how to collect and inpect the code and activities in one pass.
can we combine windowing function to achieve this.
Please advise and help
UPDATE:
based on the updated results, maybe the below query is what you need
So what i assume is that you need both a and c as well x1 .
So I count distinct activities which are a and c and then do integer division by 2. if only a is present then count distinct =1 but 1/2 =0 in integer division.
It is only 1 when both a and c are present.
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0
END) AS num_activity_a_or_b,
COUNT(DISTINCT CASE WHEN code IN ('x1') AND activity IN ( 'a','c')
THEN activity
ELSE NULL
END)/2 AS num_activity_a_and_c
from table_1
group by customer
Maybe your query can be
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0
END) AS num_activity_a_or_b,
SUM(CASE WHEN code IN ('x1') AND activity IN ( 'a','c')
THEN 1
ELSE 0
END) AS num_activity_a_or_c
from table_1
group by customer

Find items in table with 2 specific sizes

I have items table where the item code repeats as it has different sizes, variants.
I want to find items which has 2 specific sizes, ie size in both M/Y and Euro.
Items table:
Id size
1 0
1 2Y
1 EU-15
2 2M
2 4M
3 0
3 2M-4M
3 EU-12
4 EU-11
4 EU-15
Required, I want to query for item id 1 and 3.
I was trying with SUM(), CASE but not able to figure it as it involves LIKE operator. (Size like '[^EU]%' and Size like 'EU%')
#Update:
With little hint, I could do it with 2 queries using temp table. Would be nice to see it in single query.
1st Query.
select id,
case when size like '[^EU]%' then 'S'
when size like 'EU%' then 'EU' END as size
into #t from table
2nd Query.
select id, size from table
where id in
( select id from #t
group by id
having count(distinct(size))>1)
order by id, size
Thanks.
I think you wanted Id with both EU% and non EU%
select t.Id
from tbl t
group by t.Id
having count(distinct case when size like 'EU%' then 1 else 2 end) = 2
You can use the analytical function as follows:
select * from
(select t.*,
count(case when Size like '%M' OR Size like '%Y' then 1 end)
over (partition by id) cnt1,
count(case when Size like 'EU%' then 1 end)
over (partition by id) cnt2
from your_Table t) t
where cnt1 > 0 AND cnt2 > 0

How to count two different values in the same column and output those counts to two different columns

So I have this code already.
select
Item,
count(WORK_TYPE) AS 'Capacity Replen'
from WORK_INSTRUCTION
where WORK_TYPE = 'Replen - Capacity'
Group by ITEM
Which outputs this:
Item Capacity Replen
E000191208 3
E000191904 2
E000328017 2
E000397711 2
I need to be able to count a different Work_Type as well and output that count to the associated item.
I think you're looking for conditional aggregation.
SELECT
Item
,SUM( CASE WHEN WORK_TYPE= 'Replen - Capacity' THEN 1 ELSE 0 END) AS 'Capacity Replen'
,SUM( CASE WHEN WORK_TYPE= 'Some Other Criteria' THEN 1 ELSE 0 END) AS 'Some Other Column Name'
FROM WORK_INSTRUCTION
WHERE WORK_TYPE IN ('Replen - Capacity','Some Other Criteria')
GROUP BY ITEM

Multiple Word Count in SQL

I have a list of words I need to find in a specific column , "description of what happenned "
this holds anything up to 500 or more characters. I have the script below that does work
However how do I replace the Name column 1.2.3 with the actual name of the word I am looking for with the total next to it.
Just cant get it to display prob something simple.
select GROUPING_ID ( Amoxicillin ,Atorvastatin ) as Name ,count(*) as Total
from ( select case when [description_of_what_happened] like '%Amoxicillin%'
then 1 else 0 end as Amoxicillin ,
case when [description_of_what_happened] like '%Atorvastatin%'
then 1 else 0 end as Atorvastatin
FROM "NAME OF TABLE"
group by grouping sets (() ,(Amoxicillin),(Atorvastatin))
having coalesce (Amoxicillin,1) != 0 and coalesce (Atorvastatin,1) != 0
order by grouping_id (Amoxicillin,Atorvastatin)
row 3 being the total I need row 1 and row 2 to show the name of the product
result as below
Name Total
1 7
2 9
3 4112
You can use strings instead of flags:
select coalesce(Amoxicillin, Atorvastatin, 'Total') as Name,
count(*) as Total
from (select (case when [description_of_what_happened] like '%Amoxicillin%'
then 'Amoxicillin'
end) as Amoxicillin ,
(case when [description_of_what_happened] like '%Atorvastatin%'
then 'Atorvastatin'
end
) as Atorvastatin
from "NAME OF TABLE"
where Amoxicillin is not null or Atorvastatin is not null
group by grouping sets ((), (Amoxicillin), (Atorvastatin))
order by name;
Note that I also moved the logic in the having to the where.

Get the distinct count of values from a table with multiple where clauses

My table structure is this
id last_mod_dt nr is_u is_rog is_ror is_unv
1 x uuid1 1 1 1 0
2 y uuid1 1 0 1 1
3 z uuid2 1 1 1 1
I want the count of rows with:
is_ror=1 or is_rog =1
is_u=1
is_unv=1
All in a single query. Is it possible?
The problem I am facing is that there can be same values for nr as is the case in the table above.
Case statments provide mondo flexibility...
SELECT
sum(case
when is_ror = 1 or is_rog = 1 then 1
else 0
end) FirstCount
,sum(case
when is_u = 1 then 1
else 0
end) SecondCount
,sum(case
when is_unv = 1 then 1
else 0
end) ThirdCount
from MyTable
you can use union to get multiple results e.g.
select count(*) from table with is_ror=1 or is_rog =1
union
select count(*) from table with is_u=1
union
select count(*) from table with is_unv=1
Then the result set will contain three rows each with one of the counts.
Sounds pretty simple if "all in a single query" does not disqualify subselects;
SELECT
(SELECT COUNT(DISTINCT nr) FROM table1 WHERE is_ror=1 OR is_rog=1) cnt_ror_reg,
(SELECT COUNT(DISTINCT nr) FROM table1 WHERE is_u=1) cnt_u,
(SELECT COUNT(DISTINCT nr) FROM table1 WHERE is_unv=1) cnt_unv;
how about something like
SELECT
SUM(IF(is_u > 0 AND is_rog > 0, 1, 0)) AS count_something,
...
from table
group by nr
I think it will do the trick
I am of course not sure what you want exactly, but I believe you can use the logic to produce your desired result.