SQL Adding and Subtracting Data From Two Different Tables - mysql

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

Related

SSRS Sorting by Year group total

I have a tablix that has Customer as the row group and Month and Year as Column Groups. Sales amount is in the data area. I would like to sort the customers in descending order by the Year total sales.
I tried the following (psuedo code)
SELECT
Period (a CONCAT of YEAR(date) and MONTH(Date),
SUM(Amount),
Company
FROM [tables]
Group by Period and Company
ORDER BY Sum(Amount) Desc
I did it this way thinking that if I sorted in the query it would come through in the order I want, but obviously it's showing the customer with the highest single month sales first, not the highest year.
Thinking more about it, if I want the report to be able to span multiple years, then I have to figure out which Year to total on, but I'd be happy to restrict the report to a single Year (identified by a parameter).
When I try to sort the tablix or customer group on Sum(Fields!Amount.value, "xYear") I get the error that aggregates can include groups.
I switched from Tablix to Matrix and now sorting the Customer Group by SUM(Fields!Amount.Value) works.... kind of.
It sorts by the grand total as opposed to a given year, but I can live with that for now. Maybe I'll add a parameter that defaults to the current year and try to figure out how to use that to enforce the sort. I'm thinking I may have to get the total YTD sales by customer in a separate dataset (that doesn't display in the report).
You could do it two ways.. (not tested... it's midnight here...) assuming you have a parameter to select the sort year and the Period is a date - adjust to suit...
You could sort by an expression something like
=SUM(
IIF(
YEAR(Fields!Period.Value) = Parameters!pSortYear.Value,
Fields!Amount.Value,
0),
"myDataSetName")
NOte The dataset name must match your dataset name exactly (case sensitive) and be enclosed in double quotes.
Or.. what I normally do is do it in SQL
SELECT Period, Company, SUM(Amount) AS Amount
INTO #data
FROM myTable
GROUP BY Period, Company
SELECT d.*, s.SortOrder
FROM #data d
JOIN (
SELECT Company, ROW_NUMBER() OVER(ORDER BY Amount DESC) as SortOrder
FROM #data
WHERE Period = #pSortYear
) s on d.Company = s.Company
Then in your report you can simply sort by SortOrder
This is done off he top of my head so there could be some basic errors but hopefully close enough for you to follow.

Trying to calculate the total amount of sales for each branch since the start of the year

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.

find total amount of a customer in SQL

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

Trying to think of the best database schema for storing dates ranges that will require joins

(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.)

MYSQL Database Joined tables query pulling up limited records and adding results

I have two tables in my database that I"m trying to use one Query to get data from both for a specific report.
Table one is "Movies" and it has these fields:
Movies_ID
Name
Season
Table two is "Boxoffice" sales income for each movie:
Boxoffice_ID
Movies_ID
Date
Amount
I want to run a query to compare the opening weekends for each movie in a given season and return them as one dataset with the amounts collected added together. So I want to take each movie and get the first three days of box office for each film and add them up so that I get back a query like this
Movie A, 49.1 Million
Movie B, 42.2 Million
Movie C, 29.5 Million
Please note the amount collected only needs to output the number and I'll take care of the formatting. I'm just having trouble figuring out how to only query the first three days of box office for each movie and adding them together.
I know I could run one query and get the movies with box office and then loop over that and re-query the database but I know that with a lot of movies that isn't the most efficient way of doing things. I'm not sure if there is a way to do all of this (first three days of each movie added together) in one query but I wanted to see if someone with more advanced knowledge could help me out.
SELECT a.Name, SUM(COALESCE(b.Amount,0)) totalAmount
FROM Movies a
LEFT JOIN BoxOffice b
ON a.Movies_ID = b.Movies_ID
WHERE b.date BETWEEN DATE_ADD(CURDATE(),INTERVAL -3 DAY) AND CURDATE()
GROUP BY a.Name
if the value of CURDATE() is 2012-11-06 (which is today), it will calculate from 2012-11-03 until 2012-11-06.
followup question, how do you calculate the date? by day? by week? or what?
UPDATE 1
SELECT a.Name, SUM(COALESCE(b.Amount,0)) totalAmount
FROM Movies a
LEFT JOIN BoxOffice b
ON a.Movies_ID = b.Movies_ID
LEFT JOIN
(
SELECT movies_ID, MIN(date) minDate
FROM BoxOffice
GROUP BY Movies_ID
) c ON a.Movies_ID = c.Movies_ID
WHERE DATE(b.date) BETWEEN DATE(c.minDate) AND
DATE(DATE_ADD(c.minDate,INTERVAL 3 DAY))
GROUP BY a.Name
just join the tables on Movies_ID and add WHERE with TIMEDIFF between issue date and Date being 3 days.