Use COALESCE within SUM in MySQL SELECT statement - mysql

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.

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

MYSQL - Get a COUNT of rows from table 1 based on average of column in table 2

Hopefully somebody can help with this - had me stumped all afternoon.
I have 2 tables:
products - id | name | active
product_reviews - id | product_id | rating
The product_reviews contains multiple rows, each one containing a rating of the parent product.
What I'm trying to do is obtain a COUNT of all the products for each rating, for example:
Rating 1 or above - 50 products
Rating 2 or above - 40 products
Rating 3 or above - 30 products
Rating 4 or above - 20 products
Rating 5 - 10 products
So far I have tried WHERE, SUBQUERY, HAVING and get inconsistent results, the closest I've got so far is:
SELECT products.id FROM `products`
INNER JOIN `product_reviews` ON `product_reviews`.`product_id` = `products`.`id`
WHERE `products`.`active` = '1'
HAVING (AVG(product_reviews.rating) > 1)
...and then counting the results, but these do not seem to be correct, obviously if I use COUNT(products.id) it will say 'incorrect use of aggregate'.
You can try this query to get the number of products which are greater than or equal to one.
SELECT COUNT(DISTINCT product_reviews.product_id)
FROM `product_reviews`
INNER JOIN `products`
ON `product_reviews`.`product_id` = `products`.`id`
WHERE `products`.`active` = '1'
AND `product_reviews`.`rating` >= 1
But you have to run the query 5 times to get products for different review groups

SQL limit SELECT but not JOIN

I'm implementing pagination on my BD. My problem is when I want limit the SELECT statement but not the JOIN. Example, a product can got many prices:
SELECT * FROM product
LEFT JOIN price ON product.id == price.id_product
LIMIT 20
But I want to get 20 products with each one with their prices. How I can limit the statement SELECT, but not LEFT JOIN.
Example:
product price.id price.id_pruct price.price
1 1 1 50
2 2 1 30
3 3 1 40
4 1 20
5 2 30
SELECT * FROM product
LEFT JOIN price ON product.id == price.id_product
LIMIT 3
Return:
product price.id id_prodcut price
1 1 1 50
1 2 1 30
1 3 1 40
But I Want
product price.id id_prodcut price
1 1 1 50
1 2 1 30
1 3 1 40
1 4 1 20
2 5 2 30
3 . . .
Three products (limit 3)
Thanks. I hope you can help me.
Modify your query to limit the number of product rows before joining it to the price table. This means we want to to join the results of a query to a table, or in other words, we write a query containing a subquery:
SELECT *
FROM (
SELECT *
FROM product
ORDER BY id_product
LIMIT 3
) p
LEFT JOIN price ON p.id = price.id_product
Hope that helps.
I would write a subquery to get the three first products (or whatever condition you choose) like this:
SELECT id
FROM product
ORDER BY id
LIMIT 3;
Once I have that, I can select everything from the price table as long as the id is in that subquery. You can do this using a join:
SELECT p.*
FROM price p
JOIN(
SELECT id
FROM product
ORDER BY id
LIMIT 3) tmp ON tmp.id = p.product_id;
Here is an SQL Fiddle example using your sample data, and I also added a row that won't be returned so you can see that it works.

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)

mysql extra count field for each row

I have a query here, anyone can help me to count the total duplicated fields?
SELECT *
FROM item
INNER JOIN itemgroup on item.itemgroupid = itemgroup.itemgroupid
INNER JOIN status on status.statusid = item.status
INNER JOIN owner on owner.ownerid = item.owner
INNER JOIN
(
SELECT code //, (SELECT count(*) FROM item WHERE ....) as 'total_duplicateds'
FROM item
GROUP BY code
HAVING count(code) > 1
) dup ON item.code = dup.code
Total items: 500
Total items with duplicated codes: 149
Now I get a total of 149 fields returned, how can I add this as a new field to each row?
After the slash is how I learnt to do it but this is a little higher level for me..
Can someone help me out?
To be even more specific
What I'd like to get returned is like:
itemid | code| itemname | itemgroup | owner | total_duplicateds
1 1000 X 1 1 3
2 1000 X 2 2 3
3 1001 A 1 1 3
4 1000 B 3 1 3
5 1002 U 2 1 3
Add COUNT aggregation and GROUP BY all columns that are interesting you.