sum of subquery select - mysql

How can sum subqueries like total_3m and total_30?
SUM(p.quantity),
SUM(ptpq.procurement_quantity),
SUM(p.quantity*ptpq.procurement_quantity) as ostatok,
(SELECT SUM(op.quantity*ptpq.procurement_quantity) FROM oc_order_product op LEFT JOIN oc_order o ON (op.order_id = o.order_id) LEFT JOIN oc_procurement_to_product_quantity ptpq ON (ptpq.product_id = op.product_id) WHERE (o.order_status_id is null or (o.order_status_id != 0 AND o.order_status_id != 19 AND o.order_status_id != 8)) and op.product_id = pptp.product_id AND DATE(o.date_added) >= '2020-03-17' AND DATE(o.date_added) <= '2020-06-17') as total_3m,
(SELECT SUM(op.quantity*ptpq.procurement_quantity) FROM oc_order_product op LEFT JOIN oc_order o ON (op.order_id = o.order_id) LEFT JOIN oc_procurement_to_product_quantity ptpq ON (ptpq.product_id = op.product_id) WHERE (o.order_status_id is null or (o.order_status_id != 0 AND o.order_status_id != 19 AND o.order_status_id != 8)) and op.product_id = pptp.product_id AND DATE(o.date_added) >= '2020-05-18' AND DATE(o.date_added) <= '2020-06-17') as total_30
FROM oc_procurement_product pp
LEFT JOIN oc_procurement_product_to_product pptp ON (pp.procurement_product_id = pptp.procurement_product_id)
LEFT JOIN oc_procurement_to_product_quantity ptpq ON (ptpq.product_id = pptp.product_id)
LEFT JOIN oc_product p ON (p.product_id = pptp.product_id)
GROUP BY pp.procurement_product_id
I tried like this
(SELECT SUM(col_sum)
FROM ((SELECT SUM(op.quantity*ptpq.procurement_quantity) as col_sum
FROM oc_order_product op
LEFT JOIN oc_order o
ON (op.order_id = o.order_id)
LEFT JOIN oc_procurement_to_product_quantity ptpq
ON (ptpq.product_id = op.product_id)
WHERE (o.order_status_id is null
or (o.order_status_id != 0
AND o.order_status_id != 19
AND o.order_status_id != 8))
and op.product_id = pptp.product_id
AND DATE(o.date_added) >= '2020-03-17'
AND DATE(o.date_added) <= '2020-06-17') as total_3m))
but catch error that unknown column pptp.product_id in 'where clause'

I solved it by something like in this two answers
MySQL: Sum of multiple subqueries
MySQL: sum values from subqueries
by select from my select
SELECT
t.procurement_product_id,
SUM(t.total_3m),
SUM(t.total_30),
SUM(t.ostatok) as ostatok,
t.stock,
(SUM(t.ostatok) + t.stock) as sum_stock
FROM (
SELECT pp.procurement_product_id,
p.quantity,
ptpq.procurement_quantity,
(p.quantity*ptpq.procurement_quantity) as ostatok,
(SELECT SUM(quantity)
FROM oc_procurement_stock WHERE procurement_product_id = pp.procurement_product_id) as stock,
(SELECT SUM(op.quantity*ptpq.procurement_quantity) as col_sum FROM oc_order_product op
LEFT JOIN oc_order o ON (op.order_id = o.order_id)
LEFT JOIN oc_procurement_to_product_quantity ptpq ON (ptpq.product_id = op.product_id)
WHERE (o.order_status_id is null
OR (o.order_status_id != 0 AND o.order_status_id != 19 AND o.order_status_id != 8)) AND op.product_id = pptp.product_id
AND DATE(o.date_added) >= '2020-03-17'
AND DATE(o.date_added) <= '2020-06-17') as total_3m,
(SELECT SUM(op.quantity*ptpq.procurement_quantity)
FROM `oc_order_product` op
LEFT JOIN `oc_order` o ON (op.order_id = o.order_id)
LEFT JOIN `oc_procurement_to_product_quantity` ptpq ON (ptpq.product_id = op.product_id)
WHERE (o.order_status_id is null or (o.order_status_id != 0 AND o.order_status_id != 19 AND o.order_status_id != 8))
AND op.product_id = pptp.product_id
AND DATE(o.date_added) >= '2020-05-18'
AND DATE(o.date_added) <= '2020-06-17') as total_30
FROM oc_procurement_product pp
LEFT JOIN oc_procurement_product_to_product pptp ON (pp.procurement_product_id = pptp.procurement_product_id)
LEFT JOIN `oc_procurement_to_product_quantity` ptpq ON (ptpq.product_id = pptp.product_id)
LEFT JOIN `oc_product` p ON (p.product_id = pptp.product_id)) t GROUP BY t.procurement_product_id```

Related

How to fix MySQL query not to return nulls

Here is my query,
SELECT
p.pcode,
p.productName,
s.pcode,
MAX(s.in_stock) AS opening_stock,
SUM(s.soldQty) AS sold_qty,
MIN(s.remaining_qty) AS closing_stock,
s.date_created,
g.pcode,
g.qty,
g.received_qty,
g.received_on
FROM tbl_products p
LEFT JOIN tbl_sold_items s
ON p.pcode = s.pcode
LEFT JOIN tbl_shop_gr_items g
ON p.pcode = g.pcode
WHERE
(s.date_created = '2019-09-27') AND
(g.received_on = '2019-09-27')
GROUP BY p.pcode
stock_report_sample
When the above query is executed it return null values when one of the selected table doesn't have the item id for that particular day. I want it to show a list of all the items(products) available even though the item has not been sold or received so that in those instances it should show zero (0)
Maybe you can use ISNULL to show zero value if NULL
SELECT
p.pcode,
p.productName,
s.pcode,
ISNULL(MAX(s.in_stock),0) AS opening_stock,
ISNULL(SUM(s.soldQty),0) AS sold_qty,
ISNULL(MIN(s.remaining_qty),0) AS closing_stock,
s.date_created,
g.pcode,
g.qty,
g.received_qty,
g.received_on
FROM tbl_products p
LEFT JOIN tbl_sold_items s ON p.pcode = s.pcode
LEFT JOIN tbl_shop_gr_items g ON p.pcode = g.pcode
WHERE(s.date_created = '2019-09-27') AND (g.received_on = '2019-09-27')
GROUP BY p.pcode
SELECT
p.pcode,
p.productName,
CASE
WHEN gr_rows IS NULL AND sl_rows IS NULL THEN 0
WHEN gr_rows > 0 AND sl_rows IS NULL THEN received_stock
WHEN gr_rows > 0 AND sl_rows > 0 THEN opening_stock
ELSE 0
END AS op_stock,
IFNULL(received_stock, 0),IFNULL(sold_stock, 0)
FROM tbl_products p
LEFT JOIN (
SELECT COUNT(r.ID) AS gr_rows,r.pcode,r.received_on,SUM(r.received_qty) AS received_stock
FROM tbl_shop_gr_items r
WHERE r.received_on = '2019-10-03'
GROUP BY r.pcode
)AS r ON p.pcode = r.pcode
LEFT JOIN (
SELECT COUNT(s.ID) AS sl_rows,s.pcode,s.date_created,SUM(s.soldQty) AS sold_stock
FROM tbl_sold_items s
WHERE s.date_created = '2019-10-03'
GROUP BY s.pcode
)AS s ON p.pcode = s.pcode
LEFT JOIN (
SELECT t.ID,t.pcode,t.date_created,t.remaining_qty AS opening_stock
FROM tbl_sold_items t
WHERE t.date_created > '2019-10-03'
GROUP BY t.pcode ORDER BY t.ID
)AS t ON p.pcode = t.pcode
The above code has solved my issue

MySQL join different table on case

I'm trying to join a different table depended on the value of a "task_type" column
What is wrong with the syntax?
Thanks.
SELECT t.*,s.task_name
CASE
WHEN t.task_type = 0 THEN
LEFT JOIN scheduler_tasks s ON s.scheduler_task_id = t.task_id
WHEN t.task_type = 1 THEN
LEFT JOIN invoice_tasks s ON s.uid = t.task_id
END
FROM task_timings t
WHERE t.account_id = ? AND t.start_date >= DATE(?) AND t.start_date <= DATE(?)
I believe you want this:
SELECT t.*,
COALESCE(s.task_name, i.task_name) as task_name
FROM task_timings t LEFT JOIN
scheduler_tasks s
ON s.scheduler_task_id = t.task_id AND
t.task_type = 0 LEFT JOIN
invoice_tasks i
ON i.uid = t.task_id AND t.task_type = 1
WHERE t.account_id = ? AND t.start_date >= DATE(?) AND
t.start_date <= DATE(?);
Can you try like this :
SELECT t.*,s.task_name FROM task_timings t
CASE
WHEN t.task_type = 0 THEN
LEFT JOIN scheduler_tasks s ON s.scheduler_task_id = t.task_id
WHEN t.task_type = 1 THEN
LEFT JOIN invoice_tasks s ON s.uid = t.task_id
END
WHERE t.account_id = ? AND t.start_date >= DATE(?) AND t.start_date <= DATE(?)

Please let me know which query is efficient based on the number of rows mentioned

rows:customers - 3,000 rowslocationcodes - 40,000 rowscardinventoryalerts - 11,000 rows:cardbatch - 9,000,000 rows
The below query is taking more than 2 minutes.
SELECT cia.cia_orderamount,
cia.cia_notes,
cia.cia_mincount,
cia.cia_customerid,
cia.cia_id,
cia.cia_locationid,
lc.locationcode,
T1.instock,
c.id AS customerid,
c.customer
FROM cardinventoryalerts cia
INNER JOIN customers c ON cia.cia_customerid = c.id
AND c.useautocardorder = 1
INNER JOIN locationcodes lc ON cia.cia_locationid = lc.id
LEFT JOIN
(SELECT cb.customer,
CASE
WHEN cb.locationcode IS NULL
OR cb.locationcode = '' THEN NULL
ELSE cb.locationcode
END AS locationcode,
sum(CASE WHEN cb.issued = 'no' THEN 1 ELSE 0 END) AS instock
FROM cardbatch cb
GROUP BY cb.customer,
cb.locationcode ) AS T1 ON lc.locationcode = T1.locationcode
AND T1.customer = c.customer
WHERE (cia_mincount > T1.instock
OR T1.instock IS NULL)
UNION
SELECT cia.cia_orderamount,
cia.cia_notes,
cia.cia_mincount,
cia.cia_customerid,
cia.cia_id,
-1,
NULL,
T1.instock,
c.id AS customerid,
c.customer
FROM cardinventoryalerts cia
INNER JOIN customers c ON cia.cia_customerid = c.id
AND c.useautocardorder = 1
LEFT JOIN
(SELECT cb.customer,
-1,
sum(CASE WHEN cb.issued = 'no' THEN 1 ELSE 0 END) AS instock
FROM cardbatch cb
WHERE cb.locationcode IS NULL
OR cb.locationcode = ''
GROUP BY cb.customer ) AS T1 ON c.customer = T1.customer
WHERE (cia_mincount > T1.instock
OR T1.instock IS NULL)
AND cia.cia_locationid IS NULL
I tried to avoid UNION to better performance of the query. So i used the below Left Join, but it ran more than 2 mintues, because of Cardbatch is contain more rows.
SELECT cia.cia_orderamount,
cia.cia_notes,
cia.cia_mincount,
cia.cia_customerid,
cia.cia_id,
COALESCE(cia.cia_locationid,-1),
COALESCE(lc.locationcode,NULL),
T1.instock,
c.id AS customerid,
c.customer
FROM cardinventoryalerts cia
INNER JOIN customers c ON cia.cia_customerid = c.id
AND c.useautocardorder = 1
LEFT JOIN locationcodes lc ON cia.cia_locationid = lc.id
LEFT JOIN
(SELECT cb.customer,
CASE
WHEN cb.locationcode IS NULL
OR cb.locationcode = '' THEN NULL
ELSE cb.locationcode
END AS locationcode,
sum(CASE WHEN cb.issued = 'no' THEN 1 ELSE 0 END) AS instock
FROM cardbatch cb
GROUP BY cb.customer,
cb.locationcode ) AS T1 ON lc.locationcode = T1.locationcode
AND T1.customer = c.customer
LEFT JOIN
(SELECT cb.customer,
-1,
sum(CASE WHEN cb.issued = 'no' THEN 1 ELSE 0 END) AS instock
FROM cardbatch cb
WHERE cb.locationcode IS NULL
OR cb.locationcode = ''
GROUP BY cb.customer ) AS T2 ON c.customer = T2.customer
WHERE (cia_mincount > T1.instock
OR T1.instock IS NULL)
OR ((cia_mincount > T2.instock
OR T2.instock IS NULL)
AND cia.cia_locationid IS NULL)
Now i am trying this approach, please let me know this will work fine.
CREATE TABLE `cardbatchtemp` ( `customer` varchar(100) DEFAULT NULL, `locationcode` varchar(50) DEFAULT NULL, `instock` int(11) DEFAULT NULL , KEY `cardnumber_customer` (`customer`,`locationcode`) );
INSERT INTO `cardbatchtemp`
SELECT cb.customer,
COALESCE(cb.locationcode,' '),
sum(CASE WHEN cb.issued = 'no' THEN 1 ELSE 0 END) AS instock
FROM cardbatch cb
GROUP BY cb.customer,
COALESCE(cb.locationcode,' ');
SELECT cia.cia_orderamount,
cia.cia_notes,
cia.cia_mincount,
cia.cia_customerid,
COALESCE(cia.cia_id,-1),
COALESCE(cia.cia_locationid,NULL),
lc.locationcode,
cb.instock,
c.id AS customerid,
c.customer
FROM cardinventoryalerts cia
INNER JOIN customers c ON cia.cia_customerid = c.id
AND c.useautocardorder = 1
LEFT JOIN locationcodes lc ON cia.cia_locationid = lc.id
LEFT JOIN cardbatchtemp cb ON (lc.locationcode = cb.locationcode
OR cb.locationcode IS NULL)
AND (cb.customer = c.customer)
WHERE (cia_mincount > cb.instock
OR cb.instock IS NULL)
Please advise.
Add in WHERE cb.issued = 'no' in the left joined query and replace it with count to reduce amout of processed records
SELECT cb.customer,
CASE
WHEN cb.locationcode IS NULL
OR cb.locationcode = '' THEN NULL
ELSE cb.locationcode
END AS locationcode,
count(cb.issued) AS instock
FROM cardbatch cb
WHERE cb.issued = 'no'
GROUP BY cb.customer,
cb.locationcode

Sub-Select on MySQL

I don't know if this is possible but I'm trying to make a select queries with a couple of JOINS with a WHERE statement. What I need is a field based on a particular WHERE and another field with different WHERE.
Current SQL query:
SELECT SUM(a.totaltime), b.user_name, MONTHNAME(a.date)
FROM a
JOIN c on c.id = a.id
JOIN b on b.userid = c.userid
LEFT JOIN d on a.projid = d.projectid
LEFT JOIN e on a.account_id = e.salesorderid
LEFT JOIN f on e.salesorderid = f.salesorderid
LEFT JOIN g on d.projectid = g.projectid
WHERE c.deleted != "1" AND YEAR(DATE(NOW())) AND ( f.cf_991 = '1' OR g.cf_990 = '1')
group by user_name,MONTHNAME(a.date);
This works fine but I need to include another field this time WHERE would be:
WHERE c.deleted != "1" AND YEAR(DATE(NOW())) AND ( f.cf_991 = '0' OR g.cf_990 = '0')
Any help is greatly appreciated thanks
EDIT:
CURRENT OUTPUT IS:
total_time username MONTHNAME(a.date)
22.5 admin April
21 admin June
15 max April
So the above is based on f.cf_991 = '1' OR g.cf_990 = '1'
What I need is this:
total_time username MONTHNAME(a.date) total_time_2
22.5 admin April 5
21 admin June 9
15 max April 13
total_time_2 is based on f.cf_991 = '0' OR g.cf_990 = '0'.
SELECT SUM(CASE WHEN f.cf_991 = '1' OR g.cf_990 = '1' THEN a.totaltime END) as total_time
, b.user_name, MONTHNAME(a.date)
, SUM(CASE WHEN f.cf_991 = '0' OR g.cf_990 = '0' THEN a.totaltime END) as total_time_2
FROM a
JOIN c on c.id = a.id
JOIN b on b.userid = c.userid
LEFT JOIN d on a.projid = d.projectid
LEFT JOIN e on a.account_id = e.salesorderid
LEFT JOIN f on e.salesorderid = f.salesorderid
LEFT JOIN g on d.projectid = g.projectid
WHERE c.deleted != "1"
AND YEAR(CURDATE()) = a_column_containing_a_date
AND (
( f.cf_991 = '1' OR g.cf_990 = '1')
OR
( f.cf_991 = '0' OR g.cf_990 = '0')
)
group by user_name,MONTHNAME(a.date);
Just try this
SELECT
SUM(if(f.cf_991 = '1' || g.cf_990 = '1',a.totaltime,0)),
SUM(if(f.cf_991 = '0' || g.cf_990 = '0',a.totaltime,0)),
b.user_name, MONTHNAME(a.date) FROM a
JOIN c on c.id = a.id
JOIN b on b.userid = c.userid
LEFT JOIN d on a.projid = d.projectid
LEFT JOIN e on a.account_id = e.salesorderid
LEFT JOIN f on e.salesorderid = f.salesorderid
LEFT JOIN g on d.projectid = g.projectid
WHERE c.deleted != "1" AND YEAR(DATE(NOW()))
and (( f.cf_991 = '1' OR g.cf_990 = '1') or( f.cf_991 = '0' OR g.cf_990 = '0') )
group by ser_name,MONTHNAME(a.date);

Mysql IF statement or Case

I'm trying to get special value...
if empty p.price + ifnull = option_price_total
else special = option_price_total
.
SELECT
p.product_id,
p.price,
(SELECT ifnull(MIN(price), 'empty') AS FIELD_1 FROM etp_product_special ps WHERE ps.product_id = p.product_id AND ps.customer_group_id = '1' AND (ps.date_start = '0000-00-00' OR ps.date_start < NOW()) AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()) ORDER BY ps.priority, ps.price LIMIT 1) AS special,
///
IF special != 'empty'
Do this subquery ---v
(SELECT ifnull(MIN(price), '0.00') AS FIELD_2 FROM etp_product_option_value pov WHERE pov.product_id = p.product_id) AS option_price,
p.price + ifnull((SELECT MIN(price) AS FIELD_2 FROM etp_product_option_value pov WHERE pov.product_id = p.product_id GROUP BY p.product_id, p.price), '0.00') AS option_price_total,
/// ELSE
/// ex. special value equals 15
/// special AS option_price_total
/// Output: option_price_total = 15
(SELECT MIN(etp_product_option_value.price) AS FIELD_1 FROM etp_product_option_value WHERE etp_product_option_value.product_id = p.product_id GROUP BY etp_product_option_value.product_id) AS options,
(SELECT AVG(rating) AS total FROM etp_review r1 WHERE r1.product_id = p.product_id AND r1.`status` = '1' GROUP BY r1.product_id) AS rating
FROM
etp_product p
LEFT OUTER JOIN etp_product_description pd ON (p.product_id = pd.product_id)
LEFT OUTER JOIN etp_product_to_store p2s ON (p.product_id = p2s.product_id)
INNER JOIN etp_product_to_vendor ON (p.product_id = etp_product_to_vendor.product_id)
INNER JOIN etp_vendor ON (etp_product_to_vendor.vendor_id = etp_vendor.vendor_id)
Any idea ?