Why SQL where greater than is doesn't work? - mysql

I tried to select data where total greater than 3, but is not work, how to fix it?
SQL
SELECT p.image, p.id, p.name, sum(od.qty) AS total, sum(od.price * od.qty) AS nilai
FROM products p, order_details od, orders o
WHERE p.id = od.product_id
AND o.id = od.order_id
AND o.status = "Finished"
AND total > 6
GROUP BY p.id
ORDER BY nilai DESC
LIMIT 10
result
Total 6 still there. Any Advice?

Use having group by :
SELECT p.image, p.id, p.name, sum(od.qty) AS total, sum(od.price * od.qty) AS nilai
FROM products p, order_details od, orders o
WHERE p.id = od.product_id
AND o.id = od.order_id
AND o.status = "Finished"
GROUP BY p.id
HAVING sum(od.qty) > 3
ORDER BY nilai DESC
LIMIT 10

Related

Problem to correctly obtain more solds and visited items in MySQL

I'm having trouble getting the total of most sold and total most viewed products correctly.
Case best sellers:
SELECT p.product_id, p.title, p.description, p.specifications, p.price, p.discount, p.discount_type, p.color, p.hours, p.product_type, p.gender, p.img, p.vdo_intro, p.status, p.url, p.date_start, p.date_end, p.ip, p.product_page, p.product_code, p.brand, p.color_url,
c.category_id, c.category_url as urlcategory, c.parent,
SUM(o.order_quantity) as solds
FROM order_detail o
JOIN product p ON o.product_id = p.product_id
JOIN category_relations rcat ON rcat.product_id = p.product_id
LEFT JOIN `category` c on rcat.category_id = c.category_id
WHERE p.gender = ? AND p.status=1 AND p.date_end IS NULL
GROUP BY p.product_id
ORDER BY SUM(o.order_quantity)
DESC LIMIT 12;
In Data Base i have:
id_order order_quantity order_price order_discount order_discount_type product_id order_date
1 2 59.00 0 % 1 2022-01-31 22:49:24
2 5 59.00 0 % 20 2022-01-31 22:49:24
3 12 59.00 0 % 8 2022-01-31 22:49:24
4 5 59.00 0 % 19 2022-01-31 22:49:24
5 25 59.00 0 % 17 2022-01-31 22:49:24
6 3 59.00 0 % 1 2022-01-31 22:49:24
Result i get :
id:1 2 + 3 = 5 solds i get = 20 solds (wrong).
id:20 5 solds i get = 15 solds (wrong).
id:8 12 solds i get = 36 solds (wrong).
id:19 5 solds i get = 5 solds (ok).
id:17 25 solds i get = 50 solds (wrong).
Does anyone know what I'm doing wrong?
It look like that it is multiplying the results by records.
Case most visits:
SELECT p.product_id, p.title, p.description, p.specifications, p.price, p.discount, p.discount_type, p.color, p.hours, p.product_type, p.gender, p.img, p.vdo_intro, p.status, p.url, p.date_start, p.date_end, p.ip, p.product_page, p.product_code, p.brand, p.color_url,
c.category_id, c.category_url as urlcategory, c.parent,
SUM(v.total) as visits
FROM `visits` v
JOIN `product` p ON v.product_id = p.product_id
JOIN category_relations rcat ON rcat.product_id = p.product_id
LEFT JOIN `category` c on rcat.category_id = c.category_id
WHERE p.gender = ? AND p.status=1 AND p.date_end IS NULL
GROUP BY p.product_id
ORDER BY SUM(v.total)
DESC LIMIT 12
My database:
id_visits total ip today product_id
23 5 xxxxxxxxxxxxx1 2022-02-09 1
36 1 xxxxxxxxxxxxx4 2022-02-06 13
40 1 xxxxxxxxxxxxx3 2022-02-06 13
41 1 xxxxxxxxxxxxx1 2022-02-06 21
48 1 xxxxxxxxxxxxx2 2022-02-07 13
50 1 xxxxxxxxxxxxx2 2022-02-07 1
62 1 xxxxxxxxxxxxx8 2022-02-08 1
Result i get:
id1 : 5 + 1 + 1 = 7 visits i get 28 visits (wrong)
id13: 1 + 1 + 1 = 3 visits i get 9 visits (wrong)
id21: 1 = 1 visits i get 3 visits (wrong)
Does anyone know the error, because it does not add up correctly?
note: I can add the tables if needed
Edit:
DB Fiddle
If i do:
GROUP BY rcat.cat_relation_id
I get the calculation right, but it repeats the same products
Your problem is that category_relations is a many to many table. So when you join it you get additional results for each category that a product is in. So product id1 is in 4 categories so you get a sum of 28 instead of 7.
Your query is producing a row for each order for each category that the product ordered is in and then grouping all rows with the same product_id together. SUM will add all the values from all the rows grouped together.
If you want one line per product you need to group by product_id. You could remove the category data (3 items in SELECT and 2 JOINS), but if you need that category data in that one line per product you need to aggregate the category data with an aggregate function such as GROUP_CONCAT(). Then you can fix the sum by dividing by the number of categories. You can get the number of categories with COUNT(DISTINCT category_id).
Your queries would look like this:
SELECT
p.product_id,
p.title,
p.description,
p.specifications,
p.price,
p.discount,
p.discount_type,
p.color,
p.hours,
p.product_type,
p.gender,
p.img,
p.vdo_intro,
p.status,
p.url,
p.date_start,
p.date_end,
p.ip,
p.product_page,
p.product_code,
p.brand,
p.color_url,
GROUP_CONCAT(DISTINCT c.category_id) AS category_id,
GROUP_CONCAT(DISTINCT c.category_url) AS urlcategory,
GROUP_CONCAT(DISTINCT c.parent) AS parent,
ROUND(SUM(o.order_quantity) / COUNT(DISTINCT c.category_id)) AS solds
FROM order_detail o
JOIN product AS p ON o.product_id = p.product_id
JOIN category_relations rcat ON rcat.product_id = p.product_id
LEFT JOIN category AS c ON rcat.category_id = c.category_id
WHERE
p.gender = ? AND
p.status=1 AND
p.date_end IS NULL
GROUP BY p.product_id
ORDER BY ROUND(SUM(o.order_quantity) / COUNT(DISTINCT c.category_id)) DESC
LIMIT 12;
SELECT
p.product_id,
p.title,
p.description,
p.specifications,
p.price,
p.discount,
p.discount_type,
p.color,
p.hours,
p.product_type,
p.gender,
p.img,
p.vdo_intro,
p.status,
p.url,
p.date_start,
p.date_end,
p.ip,
p.product_page,
p.product_code,
p.brand,
p.color_url,
GROUP_CONCAT(DISTINCT c.category_id) AS category_id,
GROUP_CONCAT(DISTINCT c.category_url) AS urlcategory,
GROUP_CONCAT(DISTINCT c.parent) AS parent,
ROUND(SUM(v.total) / COUNT(DISTINCT c.category_id)) AS solds
FROM
visits AS v
JOIN product AS p ON v.product_id = p.product_id
JOIN category_relations AS rcat ON rcat.product_id = p.product_id
LEFT JOIN category AS c ON rcat.category_id = c.category_id
WHERE
p.gender = ? AND
p.status=1 AND
p.date_end IS NULL
GROUP BY p.product_id
ORDER BY ROUND(SUM(v.total) / COUNT(DISTINCT c.category_id))
DESC LIMIT 12;
DB Fiddle
(I commented some stuff in the fiddle to make it easier to see the results)
To have a consistent order for the category fields that were concatenated you can use an ORER BY clause in the GROUP CONCAT function:
GROUP_CONCAT(DISTINCT c.category_id ORDER BY c.category_id) AS category_id,
GROUP_CONCAT(DISTINCT c.category_url ORDER BY c.category_id) AS urlcategory,
GROUP_CONCAT(DISTINCT c.parent ORDER BY c.category_id) AS parent,
MySQL doc for GROUP_CONCAT
If you only need one result from categories, let's say the category with the lowest id, you can use this trick: You left join your category_relations again with a condition that category_id is lower than the first one and then in your WHERE clause only select the rows where that IS NULL - no lower category_id was found.
...
c.category_id,
c.category_url,
c.parent,
ROUND(SUM(o.order_quantity) / COUNT(DISTINCT c.category_id)) AS solds
FROM order_detail o
JOIN product AS p ON o.product_id = p.product_id
JOIN category_relations rcat ON rcat.product_id = p.product_id
LEFT JOIN category AS c ON rcat.category_id = c.category_id
LEFT JOIN category_relations AS rcat2 ON rcat.product_id = p.product_id AND rcat2.category_id < rcat.category_id
WHERE
p.gender = ? AND
p.status=1 AND
p.date_end IS NULL AND
rcat2.category_id IS NULL
GROUP BY p.product_id, c.category_id
ORDER BY ROUND(SUM(o.order_quantity) / COUNT(DISTINCT c.category_id)) DESC
...

How to do GROUP BY and COUNT(*) in JOIN MySQL

I have tables named company, product, purchase_order, skid, process_record and I want MySQL query result as below.
I tried
SELECT s.id as skidId, s.skidBarcode, po.poNumber, s.companyId, c.companyName, p.productId , p.productName, totalProcessed
FROM skid s
INNER JOIN company c ON s.companyId = c.id
INNER JOIN purchase_order po on s.purchaseOrderId = po.id
INNER JOIN product prdct on p.productId = prdct.id
LEFT JOIN (SELECT skidID, productId , COUNT(*) as processedQuantity FROM process_record GROUP BY productId ) p ON p.skidID= s.id
WHERE s.status = 'closed' ORDER By s.companyId,s.id
However, this query result gives processedQuantity count NULL and random wrong count on some rows.
How can I get the desired MySQL query output as shown in screenshot?
I added GROUP BY skidID, productId instead of GROUP BY productId and it resolved the issue.
SELECT s.id as skidId, s.skidBarcode, po.poNumber, s.companyId, c.companyName, p.productId , p.productName, totalProcessed
FROM skid s
LEFT JOIN (SELECT skidID, productId , COUNT(*) as processedQuantity FROM process_record GROUP BY skidID, productId ) p ON p.skidID= s.id
INNER JOIN company c ON s.companyId = c.id
INNER JOIN purchase_order po on s.purchaseOrderId = po.id
INNER JOIN product prdct on p.productId = prdct.id
WHERE s.status = 'closed' ORDER By s.companyId,s.id

MySQL - How to group sum top 6 and the rest

I have reports table that aggregates data each product quantity each day.
SELECT r.year, r.month, c.id, c.client_name, p.product_name, cc.country_name, sum(r.quantity) units FROM
client c
join report r on c.id = r.client_id
join product p on r.product_id = p.id
join country cc on r.country_id = c.id
WHERE r.year = year(now())
group by r.year, r.month, c.id, p.product_name, cc.country_name
I'm trying to figure out how group units sum by month, client, product and country where query shows sum for top 5 countries and rest is sum from bottom countries. Something like this:
case
when sum(r.quantity) = 'Top 1' then cc.country_name
when sum(r.quantity) = Top 2' then cc.country_name
.....
when sum(r.quantity) = 'Top 2' then cc.country_name
else 'Other'
How can I do this?
Many thanks in advance
you can try this. Here i sort the result from most quantity to less and add a row number. so the first 6 are the top.
please try it, but i cant tested.
SELECT
#nr := ( #nr +1) AS nr,
IF ( #nr < 7, CONCAT('Top ',#nr), 'other' ) AS top,
r.* FROM (
SELECT r.year, r.month, c.id, c.client_name, p.product_name, cc.country_name, sum(r.quantity) units
FROM CLIENT c
JOIN report r ON c.id = r.client_id
JOIN product p ON r.product_id = p.id
JOIN country cc ON r.country_id = c.id
WHERE r.year = YEAR(now())
GROUP BY r.year, r.month, c.id, p.product_name, cc.country_name
ORDER BY sum(r.quantity) DESC
) AS r
CROSS JOIN ( SELECT #nr:=0 ) AS params;

Mysql how to put a limit on a table with join

I want to LIMIT timber orders query to 10 for pagination. The problem i'm having is the LEFT JOIN timber_order_products is counted with the LIMIT. The LIMIT should only apply to timber_orders.
$data = $DB2->query("
SELECT o.order_id
, o.order_status
, o.customer_method
, o.payment_method
, o.customer_notes
, o.order_date
, p.name product_name
, p.price product_price
FROM timber_orders o
LEFT
JOIN timber_order_products p
ON p.order_id = o.order_id
ORDER
BY order_id DESC
LIMIT 10
");
How do i LIMIT results only from a specific table? The LIMIT 10 should only apply to timber_orders. I can't group by because i need the timber_order_products rows.
You can use a subquery:
SELECT o.order_id , o.order_status, o.customer_method, o.payment_method,
o.customer_notes, o.order_date,
p.name as product_name, p.price as product_price
FROM (select o.*
from timber_orders o
order by order_id desc
limit 10
) o LEFT JOIN
timber_order_products p
on p.order_id = o.order_id
ORDER BY o.order_id DESC
LIMIT 10
Avoiding using a sub query, I would use GROUP_CONCAT. Then the products name and price can be split off in the code that displays the data:-
SELECT o.order_id
, o.order_status
, o.customer_method
, o.payment_method
, o.customer_notes
, o.order_date
, GROUP_CONCAT(CONCAT_WS('~', p.name, p.price)) AS product_name_price
FROM timber_orders o
LEFT OUTER JOIN timber_order_products p
ON p.order_id = o.order_id
GROUP BY o.order_id
, o.order_status
, o.customer_method
, o.payment_method
, o.customer_notes
, o.order_date
ORDER BY order_id DESC
LIMIT 10

mysql in only return distinct?

select sum(price)
from product
where id in (select productid
from orders where status!=0
and userid=1)
if my returned productid = (1,2,2)
the sum will only be sum of 1 and 2 instead of sum of 1,2,and2
i tried
select sum(price) from product where id in (1,2,2)
same result, how do i get indistinct sum?
SELECT SUM(p.price)
FROM product AS p
LEFT JOIN orders AS o
ON p.id = o.productid
WHERE o.productid IS NOT NULL
AND o.status <> 0
AND o.userid = 1