MySQL query to calculate rent owed based on a partial payment - mysql

I could probably do the following via PHP code but I feel it could most likely been accomplished in MySQL, so just looking for someone to help me out on a query.
I have a contract table which defines a customer monthly payment, let's say for example it is £500 per month. I then have another table called rent, where every month rent is inputted. Each rent has a status called Paid, Unpaid and Partial.
My query so far is the following, do I have to do multiple sub-queries, or is their a simple way.
SELECT cc.property_id, cc.property_rent, r.order_total, r.order_status,
SUM(CASE WHEN r.order_status = 'Partial' THEN cc.property_rent - r.order_total ELSE 0 END) AS partial_rent_owed
FROM t_customers_contract cc JOIN
t_customers_rent r
ON cc.customer_id = r.customer_id WHERE cc.property_id = 62 AND r.transaction_type = 'rent' AND
(r.date_created BETWEEN '2017-04-05' AND '2019-04-05')
GROUP BY cc.property_id
Basically, if the rent status is partial then subtract it from what is usually and then total sum of what is owed.
The desired result would be in the total SUM of what is owed and what has been contributed per property as a following output:
property_id, total_rent_made, total_rent_owed
The current contract table structure and data is as follows:
The current rent table structure and data is as follows:
As you can see order_id 20 and 27 are Partial payments and the actual payment to be made based on the contract for these ID's should be 750 and 700.

I have managed to resolve it, it is the following query. If anyone can improve it, happy to take a suggestion based on performance or it being more cleaner.
SELECT cc.property_id,
SUM(CASE WHEN r.order_status = 'Partial' THEN (cc.property_rent - r.order_total) ELSE 0 END) AS partial_rent_owed
FROM t_customers_contract cc JOIN t_customers_rent r ON (cc.property_id = r.property_id)
WHERE cc.contract_id = r.contract_id
AND cc.customer_id = 7866
AND r.transaction_type = 'rent'
AND (r.date_created BETWEEN '2016-04-05' AND '2019-04-05')
GROUP BY cc.property_id

Related

How to query the most profitable item in a specific year in MySQL

I have a practice problem where I am to write a query to find the top most 15 percent profitable products in the year 2005 from a database. The database does NOT have attributes like "Saleprice, or Purchaseprice". It has tables like PUrchaseProductDetails or SalesOrderDetails, and other stuff with Unitprice, orderquantity, ProdID, LIstPrice, ActualCost, StandardPrice, etc as attributes. I am confused as to which one I should use and how to come up with a formula. I tried to write a query, but got infinitely running results.
SELECT A.ProdID, B.ProdID, A.Unitprice - (B.Unitprice * orderquantity) Profit
FROM SalesOrderDetails A join PurchaseOrderD B
ON A.ProdID = B.ProdID
WHERE year(DateOrdered) = 2005
Group by A.ProdID
I have spent hours on these type of questions and my brain is at a dead end right now. If someone can please direct me to do it the right way, it would really help me out.
SELECT sale.ProdID, sum(sale.Unitprice - buy.Unitprice) * sale.Qty AS profit
FROM SalesOrderDetails AS sale
JOIN PurchaseOrderD AS buy ON ...
WHERE year(...) = 2005
GROUP BY 1
ORDER BY 2 DESC
LIMIT 15

MySQL alternative to subquery/join

I am looking for an efficient alternative to subqueries/joins for this query. Let's say I a table that stores information about companies with the following columns:
name: the name of the company
state: the state the company is located
in
revenue: the annual revenue of the company
employees: how many
employees this company has
active_business: wether or not the company
is in business (1 = yes, 0 = no)
Let's say that from this table, I want to find out how many companies in each state meet the requirement for some minimum amount of revenue, and also how many companies meet the requirement for some minimum number of employees. This can be expressed as the following subquery (can also be written as a a join):
SELECT state,
(
SELECT count(*)
FROM records AS a
WHERE a.state = records.state
AND a.revenue > 1000000
) AS companies_with_min_revenue,
(
SELECT count(*)
FROM records AS a
WHERE a.state = records.state
AND a.employees > 10
) AS companies_with_min_employees
FROM records
WHERE active_business = 1
GROUP BY state
My question is this. Can I do this without the subqueries or joins? Since the query is already iterating over each row (there's no indexes), is there some way I can add a condition that if the row meets the minimum revenue requirements and is in the same state, it will increment some sort of counter for the query (similar to map/reduce)?
I think CASE and SUM will solve it:
SELECT state
, SUM(CASE WHEN R.revenue > 1000000 THEN 1 ELSE 0 END) AS companies_with_min_revenue
, SUM(CASE WHEN R.employees > 10 THEN 1 ELSE 0 END) AS companies_with_min_employees
FROM records R
WHERE R.active_business = 1
GROUP BY R.state
As you can see, we will have a value of 1 per record with a revenue of greater than 1000000 (else 0), then we'll take the sum. The same goes with the other column.
Thanks to this StackOverflow question. You'll find this when you search "sql conditional count" in google.

Build sql query from multiple tables for cyfe dashboard

For the purpose of monitoring my data from my users I want to visualise my data in a Cohort analysis. Lets say that i have the following tables in my database:
Table: track_register
user_id, date, time
And in the following table:
Table: track_loginuser_id, date, time, succes
How i want my cohort analysis to look is like:
Months Sign Ups loged in more then once
May 40 80%
I am using Cyfe to visualise this so the data has to be formatted in a table like this:
Month,Sign Ups,Loged in more then once
May 2015,40,32
Jun 2015,60,55
(click here for cyfe example)
Eventually i want to add more data to the cohort from other tables such as percentage of users who actually bought the product and more of that good stuff.
The first set of data (the signups per month) is not the hard part. But what i am struggling with is how to fetch the data from the track login table. I will have to count the number of times a specific user has loged in and if thats > 1 then +1. I can imagine that u use CASE for that. The trouble is to separated it by the correct moth. Because the moth where de +1 supposed to go needs to be fetched from the track_register table.
Its seems kind of hard to me to put this all in one single query? But if it couldn't be done why go to the trouble of building a cohort analysis on cyfe?
Hi DATE as field name is restricted so I used DATA.
You can try this code:
SELECT TO_CHAR(NVL(a.data, b.data), 'MON YYYY') months
, COUNT(DISTINCT a.login) sign_ups
, SUM(CASE WHEN COUNT(DISTINCT b.login) > 1 THEN 1 ELSE 0 END) Loged_in_more_then_once
FROM track_register a LEFT JOIN track_login b ON a.login = b.login
GROUP BY TO_CHAR(NVL(a.data, b.data), 'MON YYYY')
ORDER BY 1
Or:
SELECT TO_CHAR(NVL(a.data, b.data), 'MON YYYY') months
, COUNT(DISTINCT a.login) sign_ups
, SUM(CASE WHEN COUNT(DISTINCT b.login) > 1 THEN 1 ELSE 0 END) Loged_in_more_then_once
FROM track_register a LEFT JOIN track_login b
ON a.login = b.login AND LAST_DAY(a.data) = LAST_DAY(b.data)
GROUP BY TO_CHAR(NVL(a.data, b.data), 'MON YYYY')
ORDER BY 1

FIFO in MySQL db

I'm using Mysql (not MSSQL) database and bumped onto a problem I seem to be unable to solve. I would very much appreciate your help finding a solution.
I'd like to create a view using two tables, as described below:
1. product_in
product_code
received_time
received_amount
2. product_out
product_code
delivery_time
delivered_amount
The “view” should provide the following:
product_code
received_time
received_amount
of_which_delivered
My problem is that product_out is to be administered to the first incoming data (FIFO: first in first out), but since the amount delivered is either more or less than the received amount, I do not know how to calculate the “of_which_delivered”.
So far, I managed to put into order the incoming data, and sum up the outgoing (delivered) goods using SUM.
SELECT
sn,
product_code,
received_time,
received_amount,
delivered_amount
FROM
( SELECT
received_time,
received_amount,
#rend2 := If( #rend1 = product_code, #rend2 + 1, 1) as sn,
#rend1 := product_code AS product
FROM
product_in,
( SELECT #rend1 := 0, #rend2 := 0 ) AS tt
ORDER BY
product_code,
received_time ) AS k
LEFT JOIN
( SELECT
product_code AS prdct,
SUM(delivered_amount) AS delivered_amount
FROM
product_out
GROUP BY
product_code ) AS b
ON aru = product_code
I have not succeded in creating the loop that would make it possible to analyze if the output amount is more, or less than the received amount on a given day, and if more, then the difference be added to the received amount of another day.
To be more precise, here is an example:
Product Date Qty
nr.1 Sep 2 500
nr.1 Sep 3 300
nr1. Sep 4 200 on the 4th.
900 pcs were delivered out on the 5th.
In this case we should see the following in the view:
Product Action Date Qty
nr.1 received Sep 2 500 (delivered all 500)
nr.1 received Sep 3 300 (delivered all 300)
nr.1 received Sep 4 200 (only 100 delivered)
I would be very grateful to anyone who could help me find a solution!
Sorry no query adjustment for you, but... having worked with accounting systems in the past, your database structure appears short on a better handling of the in/out FIFO method (or even LIFO). What the underlying accounting system had was a inventory table for all receipts (abbreviated)
Table: ItemTrans
ItemTransID (auto-increment ID for any transaction)
ItemID (item id of the inventory item)
Status (status, such as In, Our or Inventory Adjustment)
Date (date of the activity)
Qty (quantity)
QtyUsed (running total column as inventory was used up)
As items were sold or adjustments. the Sales Details table would show which ItemTrans record the quantities were used for. So, if you had inventory on hand as you have in your sample, the sales order detail line would show the 900. The inventory used table would show which specific ItemTransID the quantities were allocated from and how many from said block, thus showing what your intended activity of release of actual product was at the time of sale.
This way, you don't have to recreate what inventory was what at a given point in time. Just query the sales order details and which items they were pulled from to get the data and how many from each block of receipt it went against.
This simplifies the process of generating the COGS (cost of goods sold) as would be reported to the General Ledger from a Sub-journal such as Accounts Receivable (Sales Orders) activity.
Do you have the ability to introduce such adjustments to your database structures?

SQL Script for Counting Records based on specific criteria and returning the Counts

I'm Trying to count records with specific criteria in my Database to ultimately produce some statistical reports.
My Tables and Fields are:
1- Import Table:bed_ID, unit_ID, mrn, acccount_num, sex, service_ID
2- Beds: bed_ID, unit_ID, bed_type_ID
3- Bed_Type: bed_type_ID, bed_type_description
4- Unit: unit_ID, unit_common_name, program_ID, total_beds...other fields that don't apply.
5- Service: service_ID, service_common_name, program_ID
6- Program: program_ID, program_common_name
I want to create a query that will give me a count of each Bed_Type_Description for each Unit. I also want to get each units total beds and calculate beds available but I'm sure I can figure that out if I get help with this part.
Unit Regular_Bed Escalation_Bed Transfer_Bed Bassinet
-------------------------------------------------------------
Unit1 10 4 2 2
Unit2 12 2 2 0
etc...
etc...
This is what I have, but its only related to one specific Unit:
SELECT
COUNT(dw_test.dbo.Bed_Type.bed_type_description) as 'Total Number of Beds'
FROM
dw_test.dbo.MediTechReport_Bed_Board,
--dw_test.dbo.Unit,
dw_test.dbo.Beds,
dw_test.dbo.Bed_Type
WHERE
dw_test.dbo.MediTechReport_Bed_Board.bed_ID = dw_test.dbo.Beds.bed_ID
--AND
-- dw_test.dbo.MediTechReport_Bed_Board.unit_ID = dw_test.dbo.Unit.unit_ID
AND
dw_test.dbo.Beds.bed_type_ID = dw_test.dbo.Bed_Type.bed_type_ID
AND
dw_test.dbo.MediTechReport_Bed_Board.unit_ID = 'KA2MED'
AND
dw_test.dbo.Bed_Type.bed_type_description = 'Regular';
You'll notice a couple lines related to Unit that are commented out. With these commented out I get a returned value of '5' records which is correct. If i remove the commenting to include these lines it returns a value of '0' which makes no sense to me. If someone can explain this to me that'd be great as well.
My SQL is quite rusty, its been a while. Any assistance is greatly appreciated. Thanks again in advance for all your help.
Maybe something like this?
select t.bed_type_description, COUNT(t.bed_type_description) as 'Total Number Of Beds'
from import As I inner join Beds as b on i.bed_Id = b.bed_Id
inner join Unit as u on i.unit_Id = u.unit_Id
inner join Bed_Type as t on b.bed_type_Id = t.bed_type_Id
where u.unit_Id = 'KA2MED'
group by t.bed_type_description