I have the following two queries - one showing gross sales and one showing paid sales (the only difference between the queries is an added condition - flag_payment = 1).
The output is two columns - Supplier Name and then Gross or Paid Sales in $ (gross - query #1, paid - query #2). If possible, I would like to combine the two queries so that the output will be Supplier Name, Gross Sales and Paid Sales (i.e. 3 columns).
Query 1: Gross Sales
SELECT C.value , SUM( SL.price )
FROM sales_listings SL
INNER JOIN sales S ON SL.sale_id = S.id
INNER JOIN custom_fields_data C ON SL.listing_id = C.owner_id
WHERE C.field_id =11
GROUP BY C.value
Query 2: Paid Sales
SELECT C.value , SUM( SL.price )
FROM sales_listings SL
INNER JOIN sales S ON SL.sale_id = S.id
INNER JOIN custom_fields_data C ON SL.listing_id = C.owner_id
WHERE S.flag_payment = 1 AND C.field_id =11
GROUP BY C.value
Is there a way to combine the following two queries? Thank you!
You can use conditional aggregation:
SELECT
c.value,
SUM(CASE WHEN s.flag_payment = 0 THEN sl.price ELSE 0 END) AS GrossSales,
SUM(CASE WHEN s.flag_payment = 1 THEN sl.price ELSE 0 END) AS PaidSales
FROM sales_listings sl
INNER JOIN sales s
ON sl.sale_id = s.id
INNER JOIN custom_fields_data c
ON sl.listing_id = c.owner_id
WHERE
c.field_id = 11
GROUP BY c.value
Since in your original query for the Gross Sales, there is no filter for s.flag_payment, you can omit the conditional SUM:
SELECT
c.value,
SUM(sl.price) AS GrossSales,
SUM(CASE WHEN s.flag_payment = 1 THEN sl.price ELSE 0 END) AS PaidSales
FROM sales_listings sl
INNER JOIN sales s
ON sl.sale_id = s.id
INNER JOIN custom_fields_data c
ON sl.listing_id = c.owner_id
WHERE
c.field_id = 11
GROUP BY c.value
Related
$sql = "SELECT CC.*, CS.name as status_name, OS.name AS order_status_name, OS.id as order_status_id, O.payment_way, O.ship_country,O.bank_id,O.payment_text, O.reference_no, O.date_comp, O.rate as rate, O.currency as currency, IF(O.payment_way=4,'TEST',B.name) as bank_name, ICR.cancel_id, ICR.result, ICR.response
FROM cancels CC
INNER JOIN orders O ON O.id = CC.order_id
LEFT JOIN order_products OP ON OP.parent=O.id
LEFT JOIN product_variants PV ON PV.id=OP.product_variant_id
LEFT JOIN products P ON P.id=PV.product_id
LEFT JOIN banks B ON B.id=O.bank_id
LEFT JOIN order_status OS ON OS.id = O.status
LEFT JOIN mp_external_order AS meo ON meo.mdns_order_id = O.id
LEFT JOIN cancel_status AS CS ON CS.cname = CC.status
LEFT JOIN (SELECT IC.cancel_id, IC.result, IC.response, MAX(IC.id) AS cancels FROM internal_cancel_requests IC GROUP BY IC.cancel_id, IC.result, IC.response) AS ICR ON CC.id = ICR.cancel_id
WHERE CC.date_add BETWEEN '2021-03-10 00:00:00' AND '2021-08-10 23:59:59' AND CC.deleted = 0 AND CC.total <> 0 AND meo.id IS NULL AND CC.status NOT IN ('REF', 'M_REF') GROUP BY CC.id ORDER BY C.date_add ASC";
$query = selectQuery($sql);
in the code block above
LEFT JOIN (SELECT IC.cancel_id, IC.result, IC.response, MAX(IC.id) AS cancels FROM internal_cancel_requests IC GROUP BY IC.cancel_id, IC.result, IC.response) AS ICR ON CC.id = ICR.cancel_id
line causing slownes.
Without changing the date range and adding limits for uploaded big data. How should I change this line of code to improve performance.
internal_cancel_requests table
id
cancel_id
response
result
1
1250
xxxxx
1
2
1250
xyxyxy
0
3
1251
xx
0
in the above table For record number 1250 cancel_id, record number 2 must be brought
A have a reservation that looks something like this:
id payable time name floor
1 24 02:40:10 Benjamin 15th
2 36 02:29:10 Beverlyn 15th
3 48 02:35:16 Benjamin 15th
4 30 02:32:51 Beverlyn 15th
And an orders table where the orders details of a customer is stored.
id product
1 A
2 B
3 C
4 D
I want to return ONLY latest record from each user that is inserted. Something like this:
payable time name floor product
24 02:40:10 Benjamin 15th A
30 02:32:51 Beverlyn 15th D
attempted query:
SELECT reservation.payable, reservation.time, reservation.name, reservation.floor, orders.product
FROM orders
INNER JOIN reservation
ON orders.id = reservation.id
WHERE reservation.time =
(SELECT MAX(time)
FROM reservation)
&& reservation.floor='15th';
problem is it only returns a SINGLE record who last inputted a even names are of the users different. Which is in the case only returns this:
payable time name floor product
24 02:40:10 Benjamin 15th A
use corelated subquery
SELECT r.*,o.product
FROM reservation r
join order o ON o.id = r.id
where r.time =( select max(time) from reservation r1 where r1.name=r.name)
Using joins -
SELECT t1.payable,
t1.time,
t1.NAME,
t1.floow,
t3.product
FROM reservation t1
INNER JOIN
(
SELECT Max(time) max_time,
NAME
FROM reservation
GROUP BY NAME) t2 t1.NAME=t2.NAME
AND t1.time=t2.max_time
INNER JOIN product t3
ON (
t1.id=t3.id)
SELECT r.payable, r.time, r.name, r.floor, o.product
FROM orders as o
INNER JOIN reservation as r
ON o.id = r.id
WHERE r.time =
(SELECT MAX(time)
FROM reservation where name=r.name)
&& r.floor='15th';
You can try something like this:
/* Create tables */
CREATE TEMP TABLE orders AS
(
SELECT 1 AS id, 'A' AS product UNION
SELECT 2, 'B' UNION
SELECT 3, 'C' UNION
SELECT 4, 'D'
);
CREATE TEMP TABLE reservations AS
(
SELECT 1 AS id, 24 AS payable, '02:40:10'::TIME AS time, 'Benjamin' AS name, '15th' AS floor UNION
SELECT 2, 36 , '02:29:10 '::TIME, 'Beverlyn', '15th'UNION
SELECT 3, 48 , '02:35:16'::TIME, 'Benjamin', '15th'UNION
SELECT 4, 30 , '02:32:51 '::TIME, 'Beverlyn', '15th'
);
/* Final Selection */
SELECT a.id
, a.payable
, a.time
, a.name
, a.floor
, b.product
FROM reservations a
LEFT JOIN orders b on a.id = b.id
WHERE (name, time) IN (SELECT name, MAX(time) AS time
FROM reservations
GROUP BY 1)
ORDER BY 1;
Alternately you can also use window functions.
I have two tables called work and stuff both tables have same fields -
company, quality, quantity
I need the sum of all the quantity of work with group by company and quality and join the table with sum of all the quantity of stuff with group by company and quality
I didn't get the expected result.
SQLfiddel
http://sqlfiddle.com/#!9/eea577/6
working query
select st.company,st.quality,st.quantitys - ct.quantitys as balance from
(select company,quality,sum(quantity) as quantitys from stuff
group by quality,company) as st join (select company,quality,
sum(quantity) as quantitys from work group by quality,company)
as ct on `ct`.`company` = `st`.`company` and ct.quality = st.quality group by quality,company
u have missed the quality condition in the join
Try the following:
SELECT tableA.ID, tableA.`Year`, tableA.`Month`,
tableA.`Type`, tableA.instrument,
tableA.totalAmount, tableB.totalInstrument
FROM
(
SELECT a.ID, a.`Year`, a.`Month`,
b.`Type`, b.instrument,
SUM(b.`amount`) totalAmount
FROM `date` a
INNER JOIN `transactions` b
ON a.ID = b.id
GROUP BY b.`Type
) tableA
INNER JOIN
(
SELECT a.ID, a.`Year`, a.`Month`,
b.`Type`, b.instrument,
SUM(b.`instrument`) totalInstrument
FROM `date` a
INNER JOIN `transactions` b
ON a.ID = b.id
GROUP BY a.`Year`, a.`Month`
) tableB ON tableA.ID = tableB.ID AND
tableA.`Year` = tableB.`Year` AND
tableA.`Month` = tableB.`Month`
I been trying different combination, but I cant seems to get this to work. I have inner join tables, I want to count the number of QA ISSUE found in the records and also output those records with only QA ISSUE, How would I do that?
SELECT d.department, m.mo_number, m.part_number, c.category,
COUNT(CASE WHEN c.category = 'QA ISSUE' THEN category END) as qa_issue,
SUM(CASE WHEN c.category = 'QA ISSUE' THEN time_spent END) as time_spent
FROM master as m
INNER JOIN category as c ON c.cat_id = m.cat_id
INNER JOIN department as d ON d.dept_id = m.dept_id
WHERE m.date_created >= DATE_SUB(now(), INTERVAL 50 DAY) AND
d.department = 'Electronics'
GROUP BY m.mo_number
ORDER BY 1
To filter results by aggregates you use the HAVING clause which occurs after the GROUP BY clause. Note this is not a substitute for the WHERE clause (which chooses the rows to be aggregated).
SELECT
d.department
, m.mo_number
, m.part_number
, c.category
, COUNT(*) AS qa_issue
, SUM(time_spent) AS time_spent
FROM master AS m
INNER JOIN category AS c ON c.cat_id = m.cat_id
INNER JOIN department AS d ON d.dept_id = m.dept_id
WHERE m.date_created >= DATE_SUB(now(), INTERVAL 50 DAY)
AND d.department = 'Electronics'
AND c.category = 'QA ISSUE'
GROUP BY
d.department
, m.mo_number
, m.part_number
, c.category
HAVING COUNT(*) = 1
ORDER BY
d.department
I have also added a condition to the where clause and added all non-aggregated columns into the GROUP BY clause - which I recommend you do always.
I have 3 tables:
shops, PRIMARY KEY cid,zbid
shop_items, PRIMARY KEY id
shop_inventory, PRIMARY KEY id
shops a is related to shop_items b by the following: a.cid=b.cid AND a.zbid=b.szbid
shops is not directly related to shop_inventory
shop_items b is related to shop_inventory c by the following: b.cid=c.cid AND b.id=c.iid
Now, I would like to run a query which returns a.* (all columns from shops). That would be:
SELECT a.* FROM shops a WHERE a.cid=1 AND a.zbid!=0
Note that the WHERE clause is necessary.
Next, I want to return the number of items in each shop:
SELECT
a.*,
COUNT(b.id) items
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid
As you can see, I have added a GROUP BY clause for this to work.
Next, I want to return the average price of each item in the shop. This isn't too hard:
SELECT
a.*,
COUNT(b.id) items,
AVG(COALESCE(b.price,0)) average_price
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid
My next criteria is where it gets complicated. I also want to return the unique buyers for each shop. This can be done by querying shop_inventory c, getting the COUNT(DISTINCT c.zbid). Now remember how these tables are related; this should only be done for the rows in c which relate to an item in b which is owned by the respective shop, a.
I tried doing the following:
SELECT
a.*,
COUNT(b.id) items,
AVG(COALESCE(b.price,0)) average_price,
COUNT(DISTINCT c.zbid)
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
LEFT JOIN shop_inventory c ON c.cid=b.cid AND c.iid=b.id
WHERE a.cid=1
GROUP BY b.szbid,b.cid
However, this did not work as it messed up the items value. What is the proper way to achieve this result?
I also want to be able to return the total number of purchases made in each shop. This would be done by looking at shop_inventory c and adding up the c.quantity value for each shop. How would I add that in as well?
Try this solution:
SELECT a.*,
COALESCE(b.item_cnt, 0) AS item_cnt,
COALESCE(b.avg_price, 0) AS avg_price,
COALESCE(b.buyer_cnt, 0) AS buyer_cnt
FROM shops a
LEFT JOIN (
SELECT a.cid,
a.szbid,
COUNT(*) AS item_cnt,
AVG(a.price) AS avg_price,
b.buyer_cnt
FROM shop_items a
LEFT JOIN (
SELECT cid,
iid,
COUNT(DISTINCT zbid) AS buyer_cnt
FROM shop_inventory
WHERE cid = 1
GROUP BY cid,
iid
) b ON a.cid = b.cid AND a.id = b.iid
WHERE a.cid = 1 AND
a.szbid <> 0
GROUP BY a.cid,
a.szbid
) b ON a.cid = b.cid AND a.zbid = b.szbid
WHERE a.cid = 1 AND
a.zbid <> 0
Instead of COUNT(DISTINCT c.zbid) + LEFT JOIN shop_inventory you could write a subselect:
SELECT
a.*,
COUNT(b.id) items,
AVG(COALESCE(b.price,0)) average_price,
( SELECT COUNT(DISTINCT c.zbid)
FROM shop_inventory c
WHERE c.cid=b.cid AND c.iid=b.id
)
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid