Presenting summary information with splitting the value of a column - sql

Is there a way to bring up the following with the table below:
customer_id | loan_date | loan_amount | loan_paid | status
------------+------------+-------------+-----------+--------
customer1 04/02/2010 5000 3850 active
customer2 04/02/2010 3000 3000 completed
customer3 04/02/2010 6500 4300 defaulted
...
Avg loan, the standard deviation of all the loans, the number of loans, the total amount of defaulted, and the total amount of collected loans per month. (I have data for about 5 years).
I have no idea of where to start.

Start like this:
SELECT date_trunc('month', loan_date)
, avg(loan_amount) AS avg_loan
, stddev_samp(loan_amount) AS stddev_samp
, count(*) AS ct_loans
, count(*) FILTER (WHERE status = 'defaulted') AS ct_defaulted
, sum(loan_paid) AS sum_paid
FROM tbl
GROUP BY 1
ORDER BY 1;
Then refine. Details are unclear. Not sure what loan_paid signifies exactly, and what you want to sum exactly. And there are multiple measures under the name of "standard deviation" ...
About aggregate functions.
About date_trunc().
About GROUP BY 1:
Concatenate multiple result rows of one column into one, group by another column
About the aggregate FILTER clause:
Aggregate columns with additional (distinct) filters

Related

SQL - Monthly cumulative count of new customer based on a created date field

Thanks in advance.
I have Customer records that look like this:
Customer_Number
Create_Date
34343
01/22/2001
54554
03/03/2020
85296
01/01/2001
...
I have about a thousand of these records (customer number is unique) and the bossman wants to see how the number of customers has grown over time.
The output I need:
Customer_Count
Monthly_Bucket
7
01/01/2021
9
02/01/2021
13
03/01/2021
20
04/01/2021
The customer count is cumulative and the Monthly Bucket will just feed the graphing package to make a nice bar chart answering the question "how many customers to we have in total in a particular month and how is it growing over time".
Try the following SELECT SQL with a sub-query:
SELECT Customer_Count=
(
SELECT COUNT(s.[Create_Date])
FROM [Customer_Sales] s
WHERE MONTH(s.[Create_Date]) <= MONTH(t.[Create_Date])
), Monthly_Bucket=MONTH([Create_Date])
FROM Customer_Sales t
WHERE YEAR(t.[Create_Date]) = ????
GROUP BY MONTH(t.[Create_Date])
Where [Customer_Sales] is the sales table and ??? = your year

sharing cash with priority to creditors in sql

I have a table in sql 2014 with name "tblPaymentPlan" like this:
Creditors PlanToPay َAmount
----------------------------------
A 2017-01-20 2000
A 2017-02-20 1500
A 2017-03-20 3000
B 2017-01-25 3000
B 2017-02-25 1000
and also another table with name "tblPaid" like following:
Creditors Paid َ
-----------------
A 4500
B 3500
and the result that I expect:
Creditors PlanToPay َRemain
----------------------------------
A 2017-01-20 0
A 2017-02-20 0
A 2017-03-20 2000
B 2017-01-25 0
B 2017-02-25 500
I have no idea for doing this job at all! Would you please to help me to perform this job. Please informed that I have a lot of records in my tables.
I need this query for budget planing. (We can use numbers for defining priority instead of dates)
What you want is a running total of what is owing, from that you can subtract what has been paid.
SELECT Creditors, PlanToPay, IIF(ABS(Remain)!=Remain,0,IIF(Remain<Amount,Remain,Amount)) as Remain
FROM (SELECT pp.Creditors, pp.PlanToPay, pp.Amount,
SUM(pp.Amount) OVER(PARTITION BY pp.Creditors ORDER BY pp.PlanToPay ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)-tp.paid AS Remain
FROM tblPaymentPlan pp
JOIN (SELECT creditors, sum(paid) as paid from tblpaid group by creditors) tp
ON pp.creditors = tp.creditors) ss
ORDER By Creditors, PlanToPay
SQLFiddle
In the windowing function (SUM OVER) the PARTITION separates the creditors, the ORDER determines how the rows are arranged (by date), and the ROWS clause tells it to use all the rows in the partition before this row and include this row in the running total. We then subtract the sum of everything paid to that creditor from this running total.
This of course gives us alot of negative numbers, so we do it in a subquery. The main query checks if the absolute value of that remaining is equal to the value, true if it's positive, false if it is not, and returns the value remaining if true, or 0 if not.
UPDATE - added handling for multiple rows with value still owing
You can subtract the running total from amount in paid table and if it is less than 0, set remain to 0 else the difference of amount from the running total.
select pp.creditors,pp.plantopay,
case when sum(pp.amount) over(partition by pp.creditors order by pp.plantopay)-coalesce(pd.paid,0) <= 0 then 0
else sum(pp.amount) over(partition by pp.creditors order by pp.plantopay)-coalesce(pd.paid,0) end as remain
from tblpaymentplan pp
left join tblPaid pd on pp.creditors=pd.creditors

osclass Counting number of Sales of specifed id products

I have this table item_log:
fk_i_item_id product amount currency status
$sales = $conn->osc_dbFetchResult("SELECT COUNT(status) FROM %st_item_log WHERE fk_i_item_id = '%s' AND status = 'COMPLETED'", DB_TABLE_PREFIX,osc_logged_user_id());
echo $sales['COUNT(status)']
I want to count total number of sales of an product in the same echo.
ex
***********************************************************
fk_i_item_id product amount currency status
***********************************************************
20 Book 1 10 USD COMPLETED
21 Book 2 12 USD COMPLETED
20 Book 1 10 USD COMPLETED
23 Book 3 11 USD COMPLETED
I want an query to count the number or records.
*******************************************************************
fk_i_item_id product amount currency status Sales
*******************************************************************
20 Book 1 10 USD COMPLETED 2
21 Book 2 12 USD COMPLETED 1
23 Book 3 11 USD COMPLETED 1
You already appear to know how to use aggregate functions such as count(), albeit over the entire table.
It's also possible to use these aggregate functions over groups of rows within the table. For example, to get the number of rows for each item ID, it's a simple matter of:
select item_id,
count(*)
from some_table
group by item_id
So all you really need to do is use group by to specify a finer level of grouping since, without that, it will group over all the selected rows.
With regard to your desired output, it would probably make more sense to sum the amount (so that id 20 has an amount of 20 rather than 10) though this may well be complicated by the fact you appear to allow multiple currencies.
I'm not going to tell you how to fix that other than to state that you may need to convert the amounts to a baseline currency before summing them.
So, as a first cut, I'd be looking at something like:
select fk_i_item_id,
max(product) as product,
sum(amount) as amount,
max(currency) as currency,
max(status) as status,
count(*) as sales
from st_item_log
where status = 'COMPLETED'
group by fk_i_item_id
Note the use of the "dummy" max aggregate function on the fields you're not grouping by. This is to ensure that the rows still group on the item ID even if they have different product descriptions, currencies, or status values (though the last is impossible given the where clause).

MS Access: Rank SUM() Values

I am working on an old web app that is still using MS Access as it's data source and I have ran into issue while trying to rank SUM() values.
Let's say I have 2 different account numbers each of those account numbers has an unknown number of invoices. I need to sum up the total of all the invoices, group it by account number then add a rank (1-2).
RAW TABLE EXAMPLE...
Account | Sales | Invoice Number
001 | 400 | 123
002 | 150 | 456
001 | 300 | 789
DESIRED RESULTS...
Account | Sales | Rank
001 | 700 | 1
002 | 150 | 2
I tried...
SELECT Account, SUM(Sales) AS Sales,
(SELECT COUNT(*) FROM Invoices) AS RANK
FROM Invoices
ORDER BY Account
But that query keeps returning the number of records assigned to that account and not a rank.
This would be easier in a report, with a running count: Report - Running Count within a Group
This is not standard in a query, but you can do something with custom functions (it's elaborate, but possible):
http://support.microsoft.com/kb/94397/en-us
Easiest way is to break it up in to 2 queries, the first one is this and I've saved it as qryInvoices:
SELECT Invoices.Account, Sum(Invoices.Sales) AS Sales
FROM Invoices
GROUP BY Invoices.Account;
And then the second query uses the first as follows:
SELECT qryInvoices.Account, qryInvoices.Sales, (SELECT Count(*) FROM qryInvoices AS I WHERE I.Sales > qryInvoices.Sales)+1 AS Rank
FROM qryInvoices
ORDER BY qryInvoices.Sales DESC;
I've tested this and got the desired results as outlined in the question.
Note: It may be possible to achieve in one query using a Defined table, but in this instance it was looking a little ugly.
If you need the answer in one query, it should be
SELECT inv.*, (
SELECT 1+COUNT(*) FROM (
SELECT Account, Sum(Sales) AS Sum_sales FROM Invoices GROUP BY Account
) WHERE Sum_sales > inv.Sum_sales
) AS Rank
FROM (
SELECT Account, Sum(Sales) AS Sum_sales FROM Invoices GROUP BY Account
) inv
I have tried it on Access and it works. You may also use different names for the two instances of "Sum_sales" above to avoid confusion (in which case you can drop the "inv." prefix).

sql DB calculation moving summary‏‏‏‏‏

I would like to calculate moving summary‏‏‏‏‏:
Total amount:100
first receipt: 20
second receipt: 10
the first row in calculation column is a difference between total amount and the first receipt: 100-20=80
the second row in calculation column is a difference between the first calculated_row and the first receip: 80-10=70
The presentation is supposed to present receipt_amount, balance:
receipt_amount | balance
20 | 80
10 | 70
I'll be glad to use your help
Thanks :-)
You didn't really give us much information about your tables and how they are structured.
I'm assuming that there is an orders table that contains the total_amount and a receipt_table that contains each receipt (as a positive value):
As you also didn't specify your DBMS, this is ANSI SQL:
select sum(amount) over (order by receipt_nr) as running_sum
from (
select total_amount as amount
from orders
where order_no = 1
union all
select -1 * receipt_amount
from the_receipt_table
where order_no =
) t
First of all- thanks for your response.
I work with Cache DB which can be used both SQL and ORACLE syntax.
Basically, the data is locaed in two different tables, but I have them in one join query.
Couple of rows with different receipt amounts and each row (receipt) has the same total amount.
Foe example:
Receipt_no Receipt_amount Total_amount Balance
1 20 100 80
1 10 100 70
1 30 100 40
2 20 50 30
2 10 50 20
So, the calculation is supposed to be in a way that in the first receipt the difference calculation is made from the total_amount and all other receipts (in the same receipt_no) are being reduced from the balance
Thanks!