Generating table with SUM columns based on different conditions - mysql

I am fairly new to SQL and I am struggling with generating a table with multiple aggregates based on certain filters.
My temporary able has 3 columns where an individual is unique by Category ID AND Customer ID (i.e. there can be multiple identical Customer IDs across categories).
Category ID
Customer ID
Number of Purchases
X
A
4
X
B
10
X
C
2
Y
A
2
Y
E
6
Z
A
10
Z
C
5
Z
D
7
The output table I am looking for is basically 4 columns: grouped by category ID identifying total number of customers who have at least 3 purchases, customers who have at least 5 purchases as well as total purchases across all customers within that category. The output table would look like this:
Category_ID
Total_Customers_3
Total_Customers_5
Total_Purchases
X
2
1
16
Y
1
1
8
Z
3
3
22
When I input the following code, I get the correct total purchases column per category but the total number of customers who had at least 3 purchases per category is incorrect as the aggregates are identical across all categories.
My code:
SELECT table.categoryID AS Category_ID
(SELECT COUNT (table.customerID)
FROM table
WHERE table.purchases >=3) AS Total_Customers_3,
(SELECT COUNT (table.customerID)
FROM table
WHERE table.purchases >=5) AS Total_Customers_5,
SUM (table.purchases) AS Total_Purchases,
FROM table
GROUP BY Category_ID, Total_Customers_3, Total_Customers_5,
(P.S When I try to just GROUP BY Category_ID, I get an ERROR that syntax is incorrect because I have sub-queries in my SELECT statement.
The incorrect table (i.e. same number of total customers meeting the condition across all categories) I get looks like:
Category_ID
Total_Customers_3
Total_Customers_5
Total_Purchases
X
2
1
16
Y
2
1
8
Z
2
1
22
Update: I should have included this in the original question but I am actually looking to generate 2 columns in the same about total number of customers based on 2 conditions - one for customers with at least 3 purchases and another column for customers with at least 5 customers.

Aggregate by category, and the use conditional aggregation to get the counts and totals.
SELECT
Category_ID,
SUM(purchases >= 3) Total_Customers_3,
SUM(CASE WHEN purchases >= 3 THEN purchases ELSE 0 END) AS Num_Purchases_3,
SUM(purchases >= 5) Total_Customers_5,
SUM(CASE WHEN purchases >= 5 THEN purchases ELSE 0 END) AS Num_Purchases_5
FROM yourTable
GROUP BY Category_ID;
Demo

Related

Select from two tables mysql in a particular order because the output must have a particular structure

I have a unique situation where I have to select particular columns from two tables in a particular order. Below is the table for the vendors
vid
company
mno
phone
1
Xoxoxo
MTN
2459999999
2
Vovovo
MTN
2459998888
3
Yrewmi
Vodafone
2459997777
Here is the order_content table.
oid
vendor_id
amount
2
2
2
2
1
4
2
1
7
3
1
1
I want to select the vendor.company, vendor.mno, SUM(order_content.amount), vendor.phone for a particular ordercontent.oid selecting only vendors involved. I want to get the vendors details from the vendor table and sum up the amount for a particular order. Lets say order 2 that is old = 2.
SELECT DISTINCT vendor.company AS customerName, vendor.mno, SUM(orders_content.price) AS amount
FROM orders_content, vendor
WHERE orders_content.oid = 2
GROUP BY orders_content.oid;
The result I am expecting
customerName
mno
amount
phone
description
reference
Vooxoo
MTN
2
2459998888
orders
154013949
Xoxoxo
MTN
11
2459999999
orders
78793949
You need to specify a joining condition between the tables, and group by vid, not oid. You don't need to group by oid since the WHERE clause restricts to a single order.
SELECT vendor.company AS customerName, vendor.mno, SUM(orders_content.price) AS amount
FROM vendor
JOIN orders_content ON orders_content.vendor_id = vendor.vid
WHERE orders_content.oid = 2
GROUP BY vendor.vid

How to show all MIN of SUM(column) that has the same min value?

I've been trying to get MIN of SUM of a column by doing subqueries, however in a case where I have two same SUM values, my query only returns me one of them. Is there a way to get all of them to be shown?
So for example this table is called quantity,
date product_id quantity_start quantity_end
1/1/2020 1 10 5
1/1/2020 2 10 5
1/1/2020 3 12 1
2/2/2020 1 10 5
2/2/2020 2 11 6
2/2/2020 3 14 1
my query would be
SELECT product_id, MIN(Total) as Minimum
FROM (SELECT product_id, SUM(quantity_start - quantity_end) as Total
FROM quantity
GROUP BY product_id)T
But this will return me only one min value while there are two since both product 1 and 2 will have total of 10 from my subquery. Is there a way to write it such that it shows me both ?
Thanks!
You are correctly grouping by your sub query, but the outer query also needs a group by so:
SELECT product_id, MIN(Total) as Minimum
FROM (SELECT product_id, SUM(quantity_start - quantity_end) as Total
FROM quantity
GROUP BY product_id)T
GROUP BY product_id;
See it working here: http://sqlfiddle.com/#!9/97d7724/1

Getting the Maximum Average price based on Product Name

I have a Products table with three headers namely ProductID, ProductName and Price.I need to find the name of the product which is having maximum average price. There are multiple products and they are duplicate as well for different product ID and i need their average price.
Sample Data looks like below :
ProductID ProductName Price
1 A 18
2 A 19
3 B 10
4 C 22
5 D 21.35
6 C 25
7 A 30
8 B 40
9 E 97
10 A 31
Query that i have written is as below:
SELECT ProductName
FROM Products
group by ProductName
order by avg(Price) desc
limit 1;
But i was informed that it is not a generic solution. Can anyone please inform, what is wrong in this query.
The only problem with your query is the case where there are more than 1 products with average price equal to the maximum average price, because it returns only 1 row.
To cover this case you need to group again and use your query in the HAVING clause :
select productname
from products
group by productname
having avg(price) = (
select avg(price)
from products
group by productname
order by avg(price) desc
limit 1
);
See the demo.

Count Category products with mysql

I have to count products inside each category like I have a category A that have two childs B and C.
In B category have 10 products and C category have 5 Products.
I want to write a query that count product like A = 15 B = 10 C = 5.
I have wrote a query that count only for child categories.
My query is given below
SELECT
c.`id`,
c.`parent_id`,
c.`name`,
c.`slug`,
c.`route_id`,
c.`description`,
c.`excerpt`,
c.`sequence`,
c.`image`,
c.`seo_title`,
c.`meta`,
c.`enabled`,
(SELECT
COUNT(`product_id`)
FROM
HM_category_products
WHERE
HM_category_products.category_id IN (SELECT
HM_categories.`id`
FROM
HM_categories
WHERE
(id = c.`id` OR id = c.`parent_id`))) AS count
FROM
`HM_categories` AS c
EDITED :- Below is my tables structure. This is just an example.
Category Table
id parent_id name slug enabled
1 0 Mobiles & Tablets mobiles-tablets 1
2 1 Mobile Phones mobile-phones 1
3 1 Tablets tablets 1
4 1 Mobile Accessories mobile-accessories 1
5 0 Electronics & Computers electronics-computers 1
6 5 Cameras & Accessories cameras-accessories 1
7 5 TV - Video - Audio tv-video-audio 1
Category Product Table
product_id category_id
1 2
2 2
3 2
4 2
5 3
6 2
7 3
8 3
9 3
10 2
11 3
12 2
13 2
14 2
15 2
You hav to use the "Group by" with something like:
SELECT
category_id, COUNT(*)
FROM
HM_category_products
GROUP BY category_id
This would get your table HM_category_products Grouped by category_id so will know how mane rows of each category its in the table, whats mean you will know the number of product of each category. Then you can join this resulting table with category one to get the category info. (Sorry for my english)
The GROUP BY statement is used in conjunction with the aggregate
functions to group the result-set by one or more columns. SQL GROUP BY Statement
for more info abaut "Group by" read
12.16.2 GROUP BY Modifiers and
12.16.1 GROUP BY (Aggregate) Functions
EDIT: I see now what you whant. I already give you the direction but here its a step furder: DISCLAIMER: THIS QUERY ITS JUST EXAMPLE, IT DOSNT WORK
CREATE VIEW view_2 AS
SELECT
category_id, COUNT(*) AS product_sum
FROM
HM_category_products
GROUP BY category_id
CREATE VIEW view_1 AS
SELECT
*
FROM
HM_categories
LEFT JOIN
view_2 AS a ON HM_categories.id = a.category_id;
SELECT
id,
name,
(SELECT
SUM(product_sum)
FROM
view_1
WHERE
parent_id = final.id) as product_count
FROM
HM_categories AS final;
that way you will get the product of a parent category, your only missing a CASE on the last select "product_count" to the child categorys, but that sum its easy because you already hav it on the view_1 (again sorry for my english)

Access Totals Query Not Necessarily Returning First Record

I have a table of data like this:
id user_id A B C
=====================
1 15 1 2 3
2 15 1 2 5
3 20 1 3 9
4 20 1 3 7
I need to remove duplicate user ids and keep the record that sorts lowest when sorting by A then B then C. So using the above table, I set up a temp query (qry_temp) that simply does the sort--first on user_id, then on A, then on B, then on C. It returns the following:
id user_id A B C
====================
1 15 1 2 3
2 15 1 2 5
4 20 1 3 7
3 20 1 3 9
Then I wrote a Totals Query based on qry_temp that just had user_id (Group By) and then id (First), and I assumed this would return the following:
user_id id
===========
15 1
20 4
But it doesn't seem to do that--instead it appears to be just returning the lowest id in a group of duplicate user ids (so I get 1 and 3 instead of 1 and 4). Shouldn't the Totals query use the order of the query it's based upon? Is there a property setting in the query that might impact this or another way to get what I need? If it helps, here is the SQL:
SELECT qry_temp.user_id, First(qry_temp.ID) AS FirstOfID
FROM qry_temp
GROUP BY qry_temp.user_id;
You need a different type of query, for example:
SELECT tmp.id,
tmp.user_id,
tmp.a,
tmp.b,
tmp.c
FROM tmp
WHERE (( ( tmp.id ) IN (SELECT TOP 1 id
FROM tmp t
WHERE t.user_id = tmp.user_id
ORDER BY t.a,
t.b,
t.c,
t.id) ));
Where tmp is the name of your table. First, Last, Min and Max are not dependent on a sort order. In relational databases, sort orders are quite ephemeral.