Count Category products with mysql - 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)

Related

Getting count of rows from one table where at least one related item from another table matches criteria

I have 'products' table and related 'variations' table, one product can have one or more variations. 'variations' table has 'status' column, its value can be 0 or 1. I want to get the number of products (COUNT()) which have at least one variation of status 1. How to make a query that would do that?
[EDIT]
Ok, I thought that if I simplify the question I will get away with the table structure, but, here we go (only columns relevant to the question and some mock data):
It's actually 3 linked tables:
table 1: 'products'
id
name
1
t-shirt
2
shoes
3
shorts
table 2: variations
id
product_id
1
1
2
1
3
2
4
2
5
3
6
3
7
3
table 3: stock
variation_id
quantity
status [0 or 1]
1
10
1
2
15
1
3
0
0
4
0
0
5
0
0
6
3
1
7
0
0
So, with this data, I want to know how many products there are that have at least 1 of its 'variations' of 'status' 1 - in this example it would be 2 (product 1 and 3 have some variations with status 1, product 2 does not).
You just need SUM all the quantity GROUP BY products.id with criteria is stock.status equal 1.
SELECT id, name, SUM(quantity) AS total_quantity
FROM Products pr
LEFT JOIN Variations va ON pr.id = va.product_id
LEFT JOIN Stock st ON st.variation_id = va.id
WHERE st.status = 1
GROUP BY pr.id
Join two tables and apply where filter on status column
select count(*) as cnt
from
products p
join variations v
on p.product_id = v.product_id
where status = 1

Use COALESCE within SUM in MySQL SELECT statement

I have the following tables:
Table users
id name base_discount
1 jack 10
2 michael 20
3 richard 30
Table item
id name category_id price
1 hammer 1 10
2 knife 2 15
3 spoon 2 12
4 plate 3 20
5 tree 4 400
Table category
id name
1 tools
2 kitchen
3 dishes
4 garden
Table discount_category
id user_id category_id discount
1 1 1 20
2 1 3 25
3 3 3 10
4 1 2 15
Table discount_item
id user_id item_id discount
1 2 1 50
2 1 2 50
Now what I want to achieve. I want to attach the discount per item that a user has to the correct item. If that is not available (NULL) I want to attach the discount per category that a user has. And if that is not available (NULL), I want to attach the base discount that a user has. With the discount I then calculate the new price of the item. However, when I try using COALESCE() within SUM() I get a syntax error. What am I doing wrong?
Below is my current query:
SELECT item.id, item.name, category.id,
category.name AS category_name, item.price, SUM((100 -
COALESCE(
(
SELECT discount_item.discount
FROM discount_item
INNER JOIN users ON discount_item.user_id = users.id
WHERE users.id = '1' AND discount_item.item_id = item.id
),
(
SELECT discount_category.discount
FROM discount_category
INNER JOIN users ON discount_category.user_id = users.id
WHERE users.id = '1' AND discount_category.category_id = item.category_id
),
(
SELECT users.base_discount
FROM users
WHERE users.id = '1'
)
)) / 100 * item.price) AS new_price,
FROM item
INNER JOIN category ON item.category_id = category.id;
Please also see the below link for an SQL Fiddle (couldn't do it on sqlfiddle.com as it wouldn't load). In the example I have appended a suffix to each table name.
http://rextester.com/LCCKSD59098
You have an extra comma after new_price and before FROM ITEM, hence the error.
Rextester Demo
Do not select other columns in select if you are not using them in group by, as in other relational RDBMS, you will get error.
Also use alias for table names for better readibily and to avoid confusion.

SQL Count subcategories

I am trying to figure out how to use the count function in order to count how many subcategories each of my categories have.
My original query is as follows(where name = the category name):
select
catid,
name,
pcatid
from category
I simply want to add a column (which is not included in my DB anywhere) called 'SubCategoryCount'. This column will count for each catid how many times it is being referenced my the pcatid column, if that makes sense.
A simple example DB would be
catid name pcatid
1 Base NULL
2 Computers 1
3 Phones 1
4 Laptops 2
5 Dell 4
And i would like to produce
catid name pcatid SubCategoryCount
1 Base NULL 2
2 Computers 1 1
3 Phones 1 0
4 Laptops 2 1
5 Dell 4 0
But how would i achive this?
Thanks for your help
John
You need to join the table itself using LEFT JOIN so it will display all records in the table even if it does not have subcategory.
SELECT a.catid,
a.NAME,
a.pcatid,
COUNT(b.pcatid) SubCategoryCount
FROM category a
LEFT JOIN category b
ON a.catid = b.pcatid
GROUP BY a.catid, a.NAME, a.pcatid
SQLFiddle Demo
PS: This query is just a projection of result without changing the original schema of the table. it doesn't physically add new column on table category.

MySQL order by points from 2nd table

So I have MySQL 3 tables, items (which in this case are lodging properties and the data is simplified below), amenities that the properties might offer, and amenities_index which is a list of item ids and amenity ids for each amenity offered. The end user can select any number of amenities they want and I want to return the results in order of the number of amenities that match what they are looking for. So, if they search for 3 different amenities, I want the items listed that offer all 3, then those that offer 2, 1 and finally the rest of the items. I have a query that I think is working for getting the results in the correct order, but I was hoping that I could also return a point value based on the matches, and that's where I'm running into trouble. My SQL skills are a bit lacking when it comes to more complex queries.
Here is an example query I have that returns the results in the correct order:
SELECT * FROM items
ORDER BY
(
SELECT count(*) AS points
FROM `amenities_index`
WHERE
(amenity_id = 1 || amenity_id = 2)
AND amenities_index.item_id = items.id
) DESC
And here is what the tables are structured like. Any help is appreciated.
items table
id name
1 location 1
2 location 2
3 location 3
4 location 4
amenities table
id name
1 fireplace
2 television
3 handicapped accessible
4 kitchenette
5 phone
amenities_index
item_id amenity_id
1 2
1 3
1 5
2 1
2 2
2 6
3 2
3 3
3 4
3 5
You want to move your expression into the select clause:
SELECT i.*,
(SELECT count(*) AS points
FROM `amenities_index` ai
WHERE amenity_id in (1, 2) AND
ai.item_id = i.id
) as points
FROM items i
ORDER BY points desc;
You can also do this as a join query with aggregation:
SELECT i.*, ai.points
FROM items i join
(select ai.item_id, count(*) as points
from amenities_index ai
where amenity_id in (1, 2)
) ai
on ai.item_id = i.id
ORDER BY ai.points desc;
In most databases, I would prefer this version over the first one. However, MySQL would allow the first in a view but not the second, so it has some strange limitations under some circumstances.

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.