How to get different status count by product id - mysql

I have got the result form a complex query below
SELECT o_items.sku,
o_items.name AS 'title',
o_items.qty_ordered AS 'quantity',
s_orders.base_amount_paid AS 'paid/unpaid'
FROM sales_order_payment s_orders
INNER JOIN (SELECT s.sku, s.name, s.qty_ordered, s.order_id
FROM sales_order_item s
INNER JOIN (SELECT p.entity_id
FROM catalog_product_entity AS p
INNER JOIN catalog_product_entity_int AS a
ON p.row_id = a.row_id
WHERE VALUE >= 0
AND
a.attribute_id =
(SELECT attribute_id
FROM eav_attribute
WHERE attribute_code = 'is_darkhorse')) as q
ON s.product_id = q.entity_id
WHERE s.created_at BETWEEN '2019-01-14' AND '2019-01-16') o_items
ON
s_orders.parent_id = o_items.order_id
this is the order data those have been paid or not paid yet. Amount is representing paid and Null representing unpaid status
I am trying to generate below result but couldn't succeed and need help. Actually this result is showing how may quantity of a product has been paid and how many not paid yet. This would be result of above fetched data.
Please guide me how can i proceed to achieve these result.

Use this. ... represent existing code.
select .... , sum(case when s_orders.base_amount_paid is not null
then o_items.qty_ordered
else 0
end) as paid,
sum(case when s_orders.base_amount_paid is null
then o_items.qty_ordered
else 0
end) as unpaid
From .......

You can use if and ifnull functions together(presuming you're using mysql as DBMS)
and GROUP BY expression
SELECT c.sku, c.name,
sum(if(ifnull(base_amount_paid,0)=0,0,1)) as paid,
sum(if(ifnull(qty_ordered,0)=0,0,1)) as unpaid
FROM catalog_prod_ent_derived c
GROUP BY c.sku, c.name
where catalog_prod_ent_derived represents your whole query as a subquery.

Related

MySQL upgrade from left join to something similar as FULL join

Sorry for asking here this but I need help and google is not being nice.
I have the following table Products
SELECT
COUNT(CASE when core.kits.Location = core.suppliers.id THEN 1 END) as total,
COUNT(CASE when core.kits.cp = 1 THEN 1 END) as used,
core.suppliers.id, core.suppliers.name, core.suppliers.email,
core.suppliers.cperson, core.suppliers.adress, core.suppliers.phone
FROM core.kits
LEFT join core.suppliers on core.kits.Location = core.suppliers.id
WHERE core.suppliers.id is not null
AND banned=0
GROUP BY core.suppliers.id
ORDER BY name ASC
LIMIT 1000 OFFSET 0
but does not give me all the suppliers with zeros for the ones who have no appearance in kits.
Then in I do
SELECT
COUNT(CASE when core.kits.Location = core.suppliers.id THEN 1 END) as total,
COUNT(CASE when core.kits.cp = 1 THEN 1 END) as used,
core.suppliers.id, core.suppliers.name, core.suppliers.email,
core.suppliers.cperson, core.suppliers.adress, core.suppliers.phone
FROM core.suppliers
LEFT join core.suppliers on core.suppliers.id = core.kits.Location
WHERE core.suppliers.id is not null
AND banned=0
GROUP BY core.suppliers.id
ORDER BY name ASC
LIMIT 1000 OFFSET 0
I get all suppliers and correct numbers but the query takes 8 seconds instead of 1s. Any ideas how can I get all the suppliers with the count of stocks in 1s?
cheers.
If you want all the suppliers, even those that do not appear in kits you should do a LEFT join of suppliers to kits:
SELECT COUNT(k.Location) AS total,
COUNT(CASE WHEN k.cp = 1 THEN 1 END) AS used,
s.id, s.name, s.email, s.cperson, s.adress, s.phone
FROM core.suppliers s LEFT JOIN core.kits k
ON k.Location = s.id
WHERE banned=0
GROUP BY s.id
ORDER BY s.name ASC
LIMIT 1000 OFFSET 0;
I assume that core.suppliers.id is the primary key of suppliers, so that the conition:
core.suppliers.id is not null
is not needed.
Also, if the column banned is contained in the table kits, then the condition should be moved in the ON clause:
ON k.Location = s.id AND k.banned=0
and the WHERE clause should be removed.

shows mysql records twice because of inner joining

In below query (Mentors) are 13 which shows me 26, while (SchoolSupervisor) are 5 which shows me 10 which is wrong. it is because of the Evidence which having 2 evidance, because of 2 evidence the Mentors & SchoolSupervisor values shows me double.
please help me out.
Query:
select t.c_id,t.province,t.district,t.cohort,t.duration,t.venue,t.v_date,t.review_level, t.activity,
SUM(CASE WHEN pr.p_association = "Mentor" THEN 1 ELSE 0 END) as Mentor,
SUM(CASE WHEN pr.p_association = "School Supervisor" THEN 1 ELSE 0 END) as SchoolSupervisor,
(CASE WHEN count(file_id) > 0 THEN "Yes" ELSE "No" END) as evidence
FROM review_m t , review_attndnce ra
LEFT JOIN participant_registration AS pr ON pr.p_id = ra.p_id
LEFT JOIN review_files AS rf ON rf.training_id = ra.c_id
WHERE 1=1 AND t.c_id = ra.c_id
group by t.c_id, ra.c_id order by t.c_id desc
enter image description here
You may perform the aggregations in a separate subquery, and then join to it:
SELECT
t.c_id,
t.province,
t.district,
t.cohort,
t.duration,
t.venue,
t.v_date,
t.review_level,
t.activity,
pr.Mentor,
pr.SchoolSupervisor,
rf.evidence
FROM review_m t
INNER JOIN review_attndnce ra
ON t.c_id = ra.c_id
LEFT JOIN
(
SELECT
p_id,
COUNT(CASE WHEN p_association = 'Mentor' THEN 1 END) AS Mentor,
COUNT(CASE WHEN p_association = 'School Supervisor' THEN 1 END) AS SchoolSupervisor,
FROM participant_registration
GROUP BY p_id
) pr
ON pr.p_id = ra.p_id
LEFT JOIN
(
SELECT
training_id,
CASE WHEN COUNT(file_id) > 0 THEN 'Yes' ELSE 'No' END AS evidence
FROM review_files
GROUP BY training_id
) rf
ON rf.training_id = ra.c_id
ORDER BY
t.c_id DESC;
Note that this also fixes another problem your query had, which was that you were selecting many columns which did not appear in the GROUP BY clause. Under this refactor, there is nothing wrong with your current select, because the aggregation take place in a separate subquery.
try adding this to the WHERE part of your query
AND pr.p_id IS NOT NULL AND rf.training_id IS NOT NULL
You can add a group by pr.p_id to remove the duplicate records there. Since, the group by on pr is not present as of now, there might be multiple records of same p_id for same ra
group by t.c_id, ra.c_id, pr.p_id order by t.c_id desc

HAVING clause not working after server update

We have just made a major upgrade in mysql version from 5.0.51 to 5.6.22 and I have just noticed that one of my queries no longer works properly.
SELECT
p.id AS product_id,
p.code,
p.description,
p.unitofmeasure,
p.costprice,
p.packsize,
vc.rateinpercent,
CASE
WHEN Sum(sales.qty) IS NULL THEN 0
ELSE Sum(sales.qty)
END AS sold,
CASE
WHEN stock.stocklevel IS NULL THEN 0
ELSE stock.stocklevel
END AS stocklevel,
sum(sales.qty) - stock.stocklevel AS diff,
CEIL((sum(sales.qty) - stock.stocklevel) / p.packsize) AS amt
FROM products p
LEFT JOIN
( SELECT
col.product_id,
col.quantity AS qty
FROM customerorderlines col
LEFT JOIN customerorders co
ON co.id = col.customerorder_id
WHERE co.orderdate >= '2014-12-01 00:00:00'
AND co.orderdate <= '2015-02-09 23:59:59'
AND co.location_id IN (1,2,3,7)
) sales
ON sales.product_id = p.id
LEFT JOIN
( SELECT
product_id,
location_id,
Sum(stocklevel) AS stocklevel
FROM stock
WHERE location_id IN (1,2,3,7)
GROUP BY product_id
) stock
ON stock.product_id = p.id
LEFT JOIN vatcodes vc
ON vc.id = p.purchasevatcode_id
WHERE p.supplier_id IN (137)
AND p.currentstatus_v = 1
GROUP BY p.id
HAVING sold > stocklevel
ORDER BY sold DESC
On the old server, the HAVING clause filtered out all results with minuses in, giving a result as follows:
Instead, I am getting the following result on the new server:
Basically, it's filtering out some of the negative results but not all of them. (The datasets are a few days old, which is why the 'Freeze Gel Spray' qty and sold and stock numbers are slightly different)
Hindsight is a wonderful thing but I didn't expect there to by any major changes for queries between server updates so I didn't care to test or check anything. Luckily this one of only two or three queries that use HAVING, so if I have to re-write a couple of queries so be it. Any ideas as to why this is though? If it wasn't working at all, fair enough, but to only be working partially?
Thanks in advance for any insight,
R
I take it you've tried EXPLAIN on the query to find out what it's doing?
Try making the calculated field names unique from the underlying field names so you can be sure what you're filtering on. I've seen some screwy results when the calculated fields have the same names as underlying physical fields.
Having your subqueries return the same format of results (i.e. both summed/grouped) helps to see what's going on.
I haven't tested this query but it may help. If you post the table structures and perhaps some fake data that shows the error, that would help diagnose
SELECT
p.id AS product_id,
p.code,
p.description,
p.unitofmeasure,
p.costprice,
p.packsize,
vc.rateinpercent,
sales.totalSold,
stock.totalStock,
sales.totalSold - stock.totalStock AS diff,
CEIL((sales.totalSold - stock.totalStock) / p.packsize) AS amt
FROM products p
LEFT JOIN (
SELECT
col.product_id,
IFNULL( SUM(col.quantity), 0) AS totalSold
FROM customerorderlines col
LEFT JOIN customerorders co
ON co.id = col.customerorder_id
WHERE co.orderdate >= '2014-12-01 00:00:00'
AND co.orderdate <= '2015-02-09 23:59:59'
AND co.location_id IN (1,2,3,7)
GROUP BY product_id
) sales
ON sales.product_id = p.id
LEFT JOIN (
SELECT
product_id,
IFNULL( SUM(stocklevel), 0) AS totalStock
FROM stock
WHERE location_id IN (1,2,3,7)
GROUP BY product_id
) stock
ON stock.product_id = p.id
LEFT JOIN vatcodes vc
ON vc.id = p.purchasevatcode_id
WHERE p.supplier_id IN (137)
AND p.currentstatus_v = 1
GROUP BY p.id
HAVING totalSold > totalStock
ORDER BY totalSold DESC

MySQL count a field into two different count results

I'm trying to COUNT attendance_status of drivers according to its value.
this is my code as of moment.
SELECT *, COUNT(attendance_status) AS total_cars_dispatched
FROM driver_attendance da
LEFT JOIN collectible co ON (da.driver_attendance_id=co.driver_attendance_id)
LEFT JOIN driver_pondo dp ON (dp.collectible_id=co.collectible_id)
WHERE attendance_status=19 AND company_id=84 GROUP BY attendance_date DESC
I'd like to know how to make another COUNT of attendance_status when it's value is 4 using a single query.
Try this:
SELECT attendance_date,
SUM(CASE WHEN attendance_status = 19 THEN 1 ELSE 0 END) AS total_cars_dispatched,
SUM(CASE WHEN attendance_status = 4 THEN 1 ELSE 0 END) AS attendance_status_4
FROM driver_attendance da
LEFT JOIN collectible co ON da.driver_attendance_id=co.driver_attendance_id
LEFT JOIN driver_pondo dp ON dp.collectible_id=co.collectible_id
WHERE company_id=84
GROUP BY attendance_date DESC;

Where clause inside joined select

I'm trying to accommodate a similar solution to this one - what I have is a SELECT query inside a JOIN, and the problem is that the query runs at full for all rows (I'm talking 60,000 rows per table - and it runs on 3 tables!).
So what I want to do, is add a WHERE clause to the SELECTs inside the JOIN.
But, I can't access the outer SELECT and get the proper WHERE condition I need.
The query I'm attempting is here:
SELECT c.compete_id AS id,
s.id AS store_id,
c.enabled AS enabled,
s.store_name AS store_name,
s.store_url AS store_url,
c.verified AS verified,
r.rating_total AS rating,
r.positive_percent AS percent,
r.type AS type
FROM compete_settings c
LEFT JOIN stores s
ON c.compete_id = s.id
LEFT JOIN (
(SELECT store_id, rating_total, positive_percent, 'ebay' AS type FROM ebay_sellers WHERE store_id = c.compete_id)
UNION
(SELECT store_id, rating_total, positive_percent, 'amazon' AS type FROM amazon_sellers WHERE store_id = c.compete_id)
UNION
(SELECT store_id, CASE WHEN rank = 0 THEN NULL ELSE (200000 - rank) END AS rating_total, '100' as positive_percent, 'alexa' AS type FROM alexa_ratings WHERE store_id = c.compete_id)
) AS r
ON c.compete_id = r.store_id
WHERE c.store_id = :store_id
Note, :store_id is a variable bound through the framework - let's imagine it's the number 12345.
How can I do this? Any ideas?
We ended up going witha different approach - we just JOINed everything and only selected the right columns with a CASE. Here's the final query:
SELECT c.id AS id,
s.id AS store_id,
c.enabled AS enabled,
s.store_name AS store_name,
s.store_url AS store_url,
c.verified AS verified,
(CASE WHEN eb.rating_total IS NOT NULL THEN eb.rating_total
WHEN am.rating_total IS NOT NULL THEN am.rating_total
WHEN ax.rank IS NOT NULL THEN ax.rank
END) AS rating,
(CASE WHEN eb.positive_percent IS NOT NULL THEN eb.positive_percent
WHEN am.positive_percent IS NOT NULL THEN am.positive_percent
WHEN ax.rank IS NOT NULL THEN '100'
END) AS percent,
(CASE WHEN eb.positive_percent IS NOT NULL THEN 'ebay'
WHEN am.positive_percent IS NOT NULL THEN 'amazon'
WHEN ax.rank IS NOT NULL THEN 'alexa'
END) AS type
FROM compete_settings c
LEFT JOIN stores s
ON c.compete_id = s.id
LEFT JOIN ebay_sellers eb ON c.compete_id = eb.store_id
LEFT JOIN amazon_sellers am ON c.compete_id = am.store_id
LEFT JOIN alexa_ratings ax ON c.compete_id = ax.store_id
WHERE c.store_id = :store_id