I have a "transactions" MySQL table on which I record all sales and refunds for my products. Each record thus either represents a sale or a refund (indicated by a flag), the transaction id, the transaction date and the value of the transaction. In case of refunds there is also a refund_id which indicates for which transaction id this refund is for.
Can I, using one query only, calculate how many sales were made in a certain time period (a sale is considered if the refund value is less than the sale value) and the overall amount earned (ie sales value minus refund value).
Notes:
1. There can be at most one refund for every sale.
2. In case of refunds the date to keep in mind is not the date when the refund was done (ie what is recorded in the DB for a particula refund), but when the original sale was done
SELECT SUM(numberofsales) as numberofsales,SUM(salevalue)
FROM (
--handle sales with refunds
SELECT count(sales) as numberofsales, sum(sales.value-refunds.value) as salevalue
FROM Transactions sales
LEFT JOIN transactions refunds ON sales.transid=refunds.refundid
WHERE refunds.refundid IS NOT NULL
AND sales.value-refund.value>0
AND sales.date>#begindate
AND sales.date<#enddate
AND sales.refund_flag='s'
UNION
--handle sales without refunds
SELECT count(sales) as numberofsales, sum(sales.value) as salevalue
FROM Transactions sales
LEFT JOIN transactions refunds ON sales.transid=refunds.refundid
WHERE refunds.refundid IS NULL
AND sales.date>#begindate
AND sales.date<#enddate
AND sales.refund_flag='s')
This is a first pass with the major charachteristics of the solution.
It's using SQL Server syntax, I'm not sure of the differences between sql server and mysql.
As per michael667's answer above, you can see the self join to get the refunds for each sale.
I dont think the group by is required.
This solution does not attempt to ensure there is only one refund for each sale, and indeed if there is more than one, it will affect the corrrectness of this solution.
This can be done using a self join in conjunction with group by.
Related
I'm currently trying to solve a problem where I'm trying to calculate the total amount of sales for each store branch since the beginning of the year, within the database I've created.
I have tried to write a query that returns the result from one store e.g London, however, there are a few more branch_ids e.g. Manchester, Cardiff etc... At the moment it only returns the London store however I'm stuck on how to also print out the other branch_ids so all branch_ids display the total turnover for each individual store.
SELECT branch_id,
date_sale,
sum(cost_order)
FROM Customer_Orders
WHERE branch_id like '%London%'
AND date_sale >='2019-01-01';
I would use this version:
SELECT
branch_id,
SUM(cost_order) AS total
FROM Customer_Orders
WHERE date_sale BETWEEN '2019-01-01' AND '2019-12-31'
GROUP BY
branch_id;
Note that it does not make sense to include the date_sale field in your select clause, because each record in the output actually corresponds to multiple dates of sale. Also, I use BETWEEN to express the year 2019, because writing it this way is SARGable, meaning that an index on date_sale can be used.
I have 2 tables in my DB
Table1 has
sales_ID
date
calls_volume
Table 2 has
sales_ID
date
sales_volume
skills_volume (the skills where the sales was logged in)
What makes things harder, is that in Table 1, there's one record per sales and date (in other words, every sales has 1 record in every day).
However table2 has one record per sales, date and skills.
When I join the two tables in a query (date and sales_id) I get the calls volume multiplied by skills volume).
can any one help me on that?
I am new in SQL, and this is my first SQL program ever my life. I want to make a program that has the following:
A table that has the record of number of loads that a customer delivered in a week, the rate(fee) for each load to deliver, the dispatch fee.
Another table that holds expenses, such us Fuel, Insurance, Trailer rent, etc.
I need to get the total sum of all expenses of a customer, and sum of all rates (earned money for each load), and then subtract the total expenses from the total net pays for each customer.
Note:
QuickPay= Rate*0.05
NetPay=Rate-(DispatchFee+QuickPay),
TotalExpenses= Fuel+Advance+Insurance+Trailer
FinalPay=NetPay-TotalExpenses
I have created one query for each table, to make the calculation, but I need to combine all in one query. Here is the code for the queries:
Query For TblLInfo
SELECT CustName, sum(Rate) AS RateFee, sum(Disp_Fee) AS DispFee, sum(Rate*0.05) AS QuickPay, sum((Rate)-((Rate*0.05)+(Disp_Fee))) AS NetPay
FROM TblLInfo
GROUP BY CustName;
Query For TblExp
SELECT CustName, sum(Fuel) AS FuelFee, sum(Advance) AS AdvanceFee, sum(Insurance) AS InsuranceFee, sum(Trailer) AS TrailerFee,
sum((Advance)+(Insurance)+(Trailer)+(Fuel)) AS TotalExp
FROM TblExp
GROUP BY CustName;
When I tried to combine them, the result is 9 (3*3), records as I expected only 3 records.
[TblLInfo,(Table Load Info), For collecting weekly loads transported one customer][1]
[TblExp (Table Expenses), For collecting weekly expenses for each customer][2]
[Query For TblLInfo, to get the sum of all loads carried specific customer and subtract the dispatch fee, so we can get the net pay][3]
[Query for TblExp, to get total expenses for specific customer][4]
![enter image description here][1]
![enter image description here][2]
SELECT a.CustName,a.NetPay,b.TotalExp,(b.TotalExp-a.NetPay) AS overall_profit
FROM
(SELECT CustName, sum(Rate) AS RateFee, sum(Disp_Fee) AS DispFee, sum(Rate*0.05) AS QuickPay, sum((Rate)-((Rate*0.05)+(Disp_Fee))) AS NetPay FROM TblLInfo GROUP BY CustName) a
INNER JOIN
(SELECT CustName, sum(Fuel) AS FuelFee, sum(Advance) AS AdvanceFee, sum(Insurance) AS InsuranceFee, sum(Trailer) AS TrailerFee, sum((Advance)+(Insurance)+(Trailer)+(Fuel)) AS TotalExp FROM TblExp GROUP BY CustName)b
i'm trying to find out the total amount of a particular customer in an inventory database.
the tables are :
customer, tax, invoice, line_no, branch, items, employee
i was able to calculate the total but i get multiple amounts as it calculates the amount for each tax rate in the database. i'm trying to restrict the amount depending on the branch issues it. i hope i made it clear, here is the query:
SELECT ROUND((SUM((LINE_NO.RETAIL_PRICE - LINE_NO.DISCOUNT)* LINE_NO.DEL_QTY)* (TAX.TAX_RATE))+
SUM((LINE_NO.RETAIL_PRICE - LINE_NO.DISCOUNT)* LINE_NO.DEL_QTY),2)
AS "TOTAL PAYMENT"
FROM LINE_NO, TAX, BRANCH
WHERE LINE_NO.INVOICE_INVOICE_NO IN (SELECT INVOICE.INVOICE_NO from INVOICE
WHERE(INVOICE.CUSTOMER_CUST_NO IN (SELECT CUST_NO from CUSTOMER where CUSTOMER.FNAME='JIM' )))
AND TAX.CITY = BRANCH.CITY
GROUP BY TAX.TAX_RATE;
GROUP BY should not operate on TAX_RATE here to avoid calculate total amount for each group (TAX_RATE).
SELECT ROUND((SUM((LINE_NO.RETAIL_PRICE - LINE_NO.DISCOUNT)* LINE_NO.DEL_QTY)* (TAX.TAX_RATE))+
SUM((LINE_NO.RETAIL_PRICE - LINE_NO.DISCOUNT)* LINE_NO.DEL_QTY),2)
AS "TOTAL PAYMENT"
FROM LINE_NO, TAX, BRANCH
WHERE LINE_NO.INVOICE_INVOICE_NO IN (SELECT INVOICE.INVOICE_NO from INVOICE
WHERE(INVOICE.CUSTOMER_CUST_NO IN (SELECT CUST_NO from CUSTOMER where CUSTOMER.FNAME='JIM' )))
AND TAX.CITY = BRANCH.CITY;
exactly. yes the rate can be retrieved from the branch location, which can be tracked by the Invoice number. so i added another query after:
AND TAX.CITY = BRANCH.CITY
which helped to determine the tax rate i'm looking for and got it working, thanks anyways
(Table names in quotes)
Let's say there are "users" that try to sells "products". They earn a commission on all "product_sales" (id, product_id, user_id, total, sale_date). I want to somehow store their commission rate based on certain dates. For example, a user will earn 1% from 2015-01-01 to 2015-01-15, 2% from 2015-01-16 to 2015-01-28, and 3% from 2015-01-29 onwards.
I want to run a query that calculates the total commissions for a user in January.
I want to run a query that calculates daily earnings in January.
How do I store the commission rates? One idea was having a table "user_commissions" that has (id, user_id, commission_rate, from_date, to_date). It would be easy to calculate the rate for (1) if commissions stayed the same, in which case I'd do this:
SELECT (sum(total) * 0.01) as total_commissions FROM product_sales WHERE user_id = 5 and sale_date between '2015-01-01' and '2015-01-31'
But with commission rates variable this is more complex. I need to somehow join the commissions table on each sale to get the right totals.
Another question would be:
How do I store the users' current commission rate that doesn't have an expiration date and include that in the reports? In my example, "3% from 2015-01-29 onwards". This has no end date.
Your table structure is a very reasonable structure and often used for slowly changing dimensions. Storing the effective and end dates in the structure is important for efficiency.
One way to store to_date for the most recent commission is to use NULL. This allows you to do:
select *
from commissions
where to_date is null
to get the most recent record.
However, a better way is to use some far distant date, such as '9999-12-12'. This allows you get the most recent commission using:
where curdate() between from_date and to_date
This is an expression that can also make use of an index on from_date, to_date.
Honestly, I would store user commission percentages and the effective dates of those commissions in one table.
TABLE: COMMISSION
user_id, date_effective, commission
In the other table I would store sales data. With each sale, I would keep the commission the salesperson got on the sale. (Added bonus, you can change the commission on any sale, like an override of sorts.)
TABLE: SALE
sale_id, sale_date, user_id, sale_amount, commission
When you create the row in your program, you can grab the correct commission rate using the following query:
SELECT commission from commission WHERE user_id=[user's id] AND date_effective<=[sale date, today] ORDER BY date_effective ASC;
MySQL Left Joins, and SQL in general, can get really tricky when trying to join on dates that don't exactly match up. (Looking back, basically.) I am struggling with the same problem right now without the luxury of the solution I just suggested.
(This whole post is based on the assumption that you aren't going to be directly interacting with this database through a DBMS but instead through an application.)