I have the following tables to allow the subscriber to sell products through the application
Order Table
OrderId
Date
1
2021-07-10
2
2021-08-24
Approval table
ApprovalId
OrderId
Status
SellerId
1
1
Accepted
10
2
1
Rejected
20
3
2
Accepted
30
Item table
ItemId
OrderId
Price
Qty
SellerId
1
1
620$
1
10
2
1
150$
2
10
3
1
410$
1
20
4
2
220$
1
30
what i want is to display the income revenue for > only who accept the order
Date
Sales
Seller_Part 90%
Net_Sales 10%
2021-07-10
770$
693$
77$
2021-08-24
220$
198%
22$
I tried using aggregate functions with group by but the result include rejected order also
select o.date
,sum(i.price * i.qty) sales
,sum(i.price * i.qty) * 0.90 Seller_Part90%
,sum(i.price * i.qty) * 0.10 Net_Sales10%
from Order o
join Approval a
on o.orderId = a.OrderId
and a.status= 'Accepted'
join Items i
on a.sellerid = i.sellerid
and a.orderid = i.orderid
group by o.date
In MySQL 5.7 I need to calculate the average discount per merchant and day.
There are 2 tables:
produts_manufacturers:
PROD_ID | MANUFACTURER_ID | PRICE_RECOM
1 1 10
2 1 20
merchants_prices
PROD_ID | MERCHANT_ID | PRICE_ACTUAL | DATE
1 10 9.00 21-01-20
1 11 8.80 21-01-20
1 11 9.00 22-01-19
My goal is a chart that gets its metric value from group by DATE, merchant_id
Now how is it possible to calculate the average discount of all products from a manufacturer at a particular merchant without also grouping by PROD_ID?
SELECT
date,
merchant_id,
1- (t.PRICE_ACTUAL / p.PRICE_RECOM)*100 AS discount2
-- (1 - ROUND(AVG(PRICE_ACTUAL),2) / p.PRICE_RECOM)*100 AS discount
FROM
merchants_prices t
INNER JOIN produts_manufacturers p ON t.PROD_ID = p.PROD_ID
WHERE
p.MANUFACTURER_ID = 1
AND PRICE_ACTUAL IS NOT NULL
GROUP by
date,
MERCHANT_ID
ORDER BY
date desc, merchant_id
To calculate average discount per merchant and day:
SELECT `DATE`, MERCHANT_ID, ROUND(AVG(discount), 2) as discount
FROM (
SELECT mp.`DATE`, mp.MERCHANT_ID, 1- (mp.PRICE_ACTUAL / pm.PRICE_RECOM)*100 AS discount
FROM produts_manufacturers pm
JOIN merchants_prices mp ON mp.PROD_ID = pm.PROD_ID
-- WHERE pm.MANUFACTURER_ID = 1 -- If you want to restrict to a specific manufacturer
) as x
GROUP BY `DATE`, MERCHANT_ID;
With your dataset ->
DATE MERCHANT_ID discount
2021-01-20 10 -89
2021-01-20 11 -87
2022-01-19 11 -89
To help you I made a fiddle here
I subtract the quantity of expired medicine to the actual stock. I use this (IFNULL(tbl_medicine.quantity - SUM(tbl_received.received_quantity),0)) AS Total and DATE(NOW()) > tbl_received.expiration_date to get the date of expired medicine. My problem is I can't get the quantity that is not expired yet. How can I get the quantity of not yet expired with expired medicine? Can somebody help me with my problem? Here's my query...
SELECT tbl_med.sup_med_id, tbl_med.quantity,
tbl_received.received_quantity, tbl_med.status,
(IFNULL(tbl_med.quantity - SUM(tbl_received.received_quantity),0)) AS Total
FROM
tbl_med
INNER JOIN
tbl_received ON tbl_received.sup_med_id = tbl_med.sup_med_id
WHERE
tbl_med.status = 'Active' AND DATE(NOW()) > tbl_received.expiration_date AND
tbl_med.barangay_id = 19
GROUP BY
sup_med_id HAVING Total > 0
ORDER BY
sup_med_id
output of query above
sup_med_id quantity received_quantity status Total
3 1800 1000 Active 800
7 1800 1000 Active 800
tbl_med & tbl_received table
id sup_med_id received_quantity expiration_date
1 3 1000 2019-09-04
2 7 1000 2019-09-04
3 9 1800 2022-09-04
medicine_id sup_med_id quantity status barangay_id
1 3 1800 Active 19
2 7 1800 Active 19
3 9 1800 Active 19
I want this to happen...
sup_med_id quantity received_quantity status Total
3 1800 1000 Active 800
7 1800 1000 Active 800
9 1800 1800 Active 1800
I just want to display the quantity to Total if the medicine is not expired yet
The issue comes from the fact you're only joining when the expiration date is in the past. To solve it that check should be removed from the WHERE clause and done in the SUM of expired quantities instead:
SELECT tbl_med.sup_med_id, tbl_med.quantity,
tbl_received.received_quantity, tbl_med.status,
(tbl_med.quantity
- SUM(CASE WHEN NOW() > tbl_received.expiration_date
THEN tbl_received.received_quantity
ELSE 0
END)
) AS Total
FROM
tbl_med
INNER JOIN
tbl_received ON tbl_received.sup_med_id = tbl_med.sup_med_id
WHERE
tbl_med.status = 'Active' AND
tbl_med.barangay_id = 19
GROUP BY
sup_med_id HAVING Total > 0
ORDER BY
sup_med_id
I haven't tested the query myself, but I believe it should achieve what you want
I've the two tables orders
id article amount
1 1 1
2 2 50
and prices
id article min_amount price
1 1 1 42.99
2 2 1 5.06
3 2 5 4.55
4 2 10 4.3
5 2 25 4.05
6 2 100 2.66
The prices tables contains IDs of articles and a minimum amount you would have to buy to get a bulk discount (which would change the price for the order). I would like to join prices into orders, so that the result looks like:
id article amount price
1 1 1 42.99
2 2 50 4.05
The order id 2 is above the minimum (25) to get the article for 4.05€, but still below 100 at which you would get a bigger discount, so the query would to have pick the next-lower value.
I've tried this query so far
SELECT
orders.id AS id,
orders.article,
orders.amount,
prices.price,
(orders.amount - prices.min_amount) AS discount_diff
FROM orders
LEFT JOIN prices ON (prices.article = orders.article) AND (prices.min_amount <= orders.amount)
which gives this result
id article amount price discount_diff
1 1 1 42.99 0
2 2 50 5.06 49
2 2 50 4.55 45
2 2 50 4.3 40
2 2 50 4.05 25
You can find this example on "js"fiddle: http://sqlfiddle.com/#!9/1b2bf/8
The query you need is this:
SELECT orders.id AS id,
orders.article,
orders.amount,
prices.price
FROM orders
INNER JOIN prices ON ( prices.article = orders.article
and prices.min_amount <= orders.amount)
INNER JOIN ( SELECT orders.article,
orders.amount,
min(prices.price) minprince
FROM orders
INNER JOIN prices ON (prices.article = orders.article
AND prices.min_amount <= orders.amount)
GROUP BY orders.article,
orders.amount) b
ON ( prices.article = b.article
AND orders.amount = b.amount
AND prices.price = b.minprince)
See it here: http://sqlfiddle.com/#!9/1b2bf/27
I'm trying to add an amount living in a transactions table, but the adding must be done taking the transactions in reversed order, grouped by a loan they belong to. Let me put some examples:
Transactions
tid loanid amount entrydate
------------------------------------
1 1 1,500 2013-06-01
2 2 1,500 2013-06-01
3 1 1,000 2013-06-02
4 3 2,300 2013-06-04
5 5 2,000 2013-06-04
6 1 1,100 2013-06-07
7 2 1,000 2013-06-09
| | | |
Loans
loanid
------
1
2
3
4
5
|
As you can see, there's no transactions for loanid 4, just to make clear the point that there's no obligation for the transactions to exist for every loan.
Now, what I'm trying to achieve is to sum up the amounts for the transactions of each loan. This first approach achieves this:
SELECT tr.tid,
l.loanid,
tr.entrydate,
tr.amount,
#prevLoan:=l.loanid prevloan,
#amnt:=if(#prevLoan:=l.loanid, #amnt+tr.amount, tr.amount) totAmnt
FROM (SELECT * FROM Transactions) tr
JOIN (SELECT #prevLoan:=0, #amnt:=0) t
JOIN Loans l
ON l.loanid = tr.loanid
GROUP BY l.loanid, tr.tid
Which achieves something like this:
tid loanid entrydate amount prevloan totAmnt
-----------------------------------------------------------
1 1 2013-06-01 1,500 1 1,500
3 1 2013-06-02 1,000 1 2,500
6 1 2013-06-07 1,100 1 3,600 <-- final result for loanid=1
2 2 2013-06-01 1,500 2 1,500
7 2 2013-06-09 1,000 2 2,500 <-- final result for loanid=2
4 3 2013-06-04 2,300 3 2,300 <-- final result for loanid=3
5 5 2013-06-04 2,000 5 2,000 <-- final result for loanid=5
| | | | | |
As you can see, for each loan, the amount of the transactions belonging to it are getting sumed up in the totAmnt column, so the last transaction of each loan has the total sum of the transactions for the same loan.
Now.... what I actually need is something to get the sum to be done in reversed order. I mean, for the same transactions of each loan, the sum still gets the same result, but I need the sum to be done from the last transaction of each loan up to the first one.
I've tried the following, but to no avail (it's the same query as the last one, but with an Order By DESC on the FROM transactions table):
SELECT tr.tid,
l.loanid,
tr.entrydate,
tr.amount,
#prevLoan:=l.loanid prevloan,
#amnt:=if(#prevLoan:=l.loanid, #amnt+tr.amount, tr.amount) totAmnt
FROM (SELECT * FROM Transactions ORDER BY tr.entrydate DESC) tr
JOIN (SELECT #prevLoan:=0, #amnt:=0) t
JOIN Loans l
ON l.loanid = tr.loanid
GROUP BY l.loanid, tr.tid
I'm using tr.entrydate because is a more familiar way to say the order criteria, and besides that's what policy says is the valid order criteria, tid may say something but entrydate is the ordering column of the Transactions table...
Using the previous query, I just get the same results I get with the first query, so I guess something must be missing there. What I need is to get results as the following:
tid loanid entrydate amount prevloan totAmnt
-----------------------------------------------------------
6 1 2013-06-07 1,100 1 1,100
3 1 2013-06-02 1,000 1 2,100
1 1 2013-06-01 1,500 1 3,600 <-- final result for loanid=1
7 2 2013-06-09 1,000 2 1,000
2 2 2013-06-01 1,500 2 2,500 <-- final result for loanid=2
4 3 2013-06-04 2,300 3 2,300 <-- final result for loanid=3
5 5 2013-06-04 2,000 5 2,000 <-- final result for loanid=5
| | | | | |
As you can see the sum for each loanid gets the same final result, but the sum is done for the transactions in reversed order...
Hope all this mess is clear... How can I achieve such a result?
You appear to be VERY close... I think you have two small adjustments. First, dont use the outer GROUP BY as you are not doing any aggregations (sum, min, max, avg, etc). Second, when querying your transaction table, just order that by the loan ID FIRST, THEN the date descending... This way all the loan IDs are in proper order grouped together, but within each loan, THEY are sorted descending order as you are looking for. Also, adjust your #prevLoan AFTER you have accumulated so the current record can be compared to the next. You are starting the #variable to zero so it won't match the first loan ID on the first run anyhow. Finally, you don't even need the join to the loan table since the transaction table has the loan ID to use as basis of comparison test. Since the inner-most query is ordered by loan and then entry date descending, you should not need it again at the outer query.
SELECT
tr.tid,
tr.loanid,
tr.entrydate,
tr.amount,
#amnt := if( #prevLoan = tr.loanid, #amnt+tr.amount, tr.amount) totAmnt,
#prevLoan := tr.loanid prevloan
FROM
( SELECT *
FROM Transactions
ORDER BY loanid, entrydate DESC) tr
JOIN (SELECT #prevLoan := 0,
#amnt := 0) t
Alternate Solution?? Per my comment, it looks like you want the high totals and shrinking down... Is this closer?
SELECT
tr.tid,
tr.loanid,
tr.entrydate,
tr.amount,
trTotals.TotalLoans - if( #prevLoan = tr.loanid, #amnt, 0 ) as NewBal,
#amnt := if( #prevLoan = tr.loanid, #amnt+tr.amount, tr.amount) runningTotals,
#prevLoan := tr.loanid prevloan
FROM
( SELECT *
FROM Transactions
ORDER BY loanid, entrydate DESC) tr
JOIN ( SELECT loanid, sum( amount ) as TotalLoans
FROM Transactions
group by loanid ) trTotals
on tr.loanid = trTotals.loanid
JOIN (SELECT #prevLoan := 0,
#amnt := 0) t
Produces... (Total Paid) (for reversing calc)
tid loanid entrydate amount NewBal Running Totals prevLoan
6 1 2013-06-07 1100 3600 1100 1
3 1 2013-06-02 1000 2500 2100 1
1 1 2013-06-01 1500 1500 3600 1
7 2 2013-06-09 1000 2500 1000 2
2 2 2013-06-01 1500 1500 2500 2
4 3 2013-06-04 2300 2300 2300 3
5 5 2013-06-04 2000 2000 2000 5