Grouping a column in oracle - sql

I have three columns within my table:
Amount, OrderNumber, Customerid
For each customerid there will be ordernumber and amount.
Now i need to display customerid,Ordernumber and Amount(total Amount- for each customerid).
custid srcnumber amount
112 4344 20
112 7678 10
112 8766 30
34 6577 15
34 4566 5
Expected:
custid srcnumber amount
112 4344 60
112 7678 60
112 8766 60
34 6577 20
34 4566 20

Use sum() over (partition by ..) analytic function to sum up the amount per each row :
select Customerid as custid,
OrderNumber as srcnumber,
sum(amount) over ( partition by Customerid ) as amount
from tab
order by custid desc
Demo

Related

PostgreSQL - Group by filter out specific rows

I have 3 tables in a Postgres 9.5 DB like below,
threshold
id threshold_amount
----------------------
111 100
112 200
113 80
customers - each customer has a threshold_id of threshold table
id customer_name threshold_id
--------------------------------
313 abc 111
314 xyz 112
315 pqr 113
charges - per customer there is charges so this table has customer_id
id customer_id amount post_date
------------------------------------
211 313 50 4/1/2017
212 313 50 4/30/2017
213 313 50 5/15/2017
214 314 100 3/1/2017
215 314 50 3/21/2017
216 314 50 4/21/2017
217 314 100 5/1/2017
218 315 80 5/5/2017
I want to query it and return the specific post_date with sum( amount ) == threshold_amount by ascending order of charges.id column,
The resultset look like below,
customer_id post_date
-----------------------
313 4/30/2017
314 4/21/2017
315 5/5/2017
I've tried sum( amount ) with group by customer_id and call the one separate the stored procedure from select clause and pass the amount, post_date and threshold_amount then created one temp table and insert post_date into it if the above condition get match and then again access that temp table but it seems something not valid so I want to know if some other solution or Can I do it in query?
Thanks
Your question is asking about an exact match for the threshold. This is basically a cumulative sum:
select cct.*
from (select ch.customer_id, ch.amount,
sum(ch.amount) over (partition by ch.customer_id order by post_date) as running_amount,
t.threshold_amount
from charges ch join
customers c
on ch.customer_id = c.id join
threshholds t
on c.threshold_id = t.id
) cct
where running_amount = threshold_amount;
try this:
select
c.customer_id,
c.post_date
from charges c
join customers cu on cu.id = c.customer_id
join threshold t on t.id = cu.threshold_id
where (select sum(cc.amount) from charges cc where cc.id <= c.id
and cc.customer_id = c.customer_id) = t.threshold_amount

How to use aggregate functions in my criteria in SQL Server?

I have table called VoucherEntry
These are my records,
ID VoucherOnlineID TransactionNumber Store Amount
-------------------------------------------------------------
120 137 26 1001 100
126 137 22 2000 -56
128 137 30 3000 -20
133 137 11 2000 -5
Now I want to add 2 columns which is having carry amount and Balance amount. If the VoucherEntry.Amount = 100 Then carry column should be 0, other wise it should display like below
Expecting output
ID VoucherOnlineID TransactionNumber Store Carry Amount Balance
---------------------------------------------------------------------------------
120 137 26 1001 0 100 100
126 137 22 2000 100 -56 44
128 137 30 3000 44 -20 24
133 137 11 2000 24 -5 19
Update
we can sort the record By ID column or Date column, after you sort the records will display in above order
You need two variations of a Cumulative Sum:
SELECT
VoucherOnlineID
,TransactionNumber
,Store
,Coalesce(Sum(Amount) -- Cumulative Sum of previous rows
Over (PARTITION BY VoucherOnlineID
ORDER BY DATE -- or whatever determines correct order
ROWS BETWEEN Unbounded Preceding AND 1 Preceding), 0) AS Carry
,Amount
,Sum(Amount) -- Cumulative Sum including current row
Over (PARTITION BY VoucherOnlineID
ORDER BY DATE -- or whatever determines correct order
ROWS Unbounded Preceding) AS Balance
FROM VoucherEntry
sql Server 2008 and below
declare #t table(ID int,VoucherOnlineID int,TransactionNumber int,Store int,Amount int)
insert into #t VALUES
(120,137,26,1001,100)
,(126,137,22,2000,-56)
,(128,137,30,3000,-20)
,(133,137,11,2000,-5 )
select *
,isnull((Select sum(Amount) from #t t1
where t1.VoucherOnlineID=t.VoucherOnlineID
and t1.id<t.id ) ,0)Carry
,isnull((Select sum(Amount) from #t t1
where t1.VoucherOnlineID=t.VoucherOnlineID
and t1.id<=t.id ) ,0)Balance
from #t t

Something like rank() in SQL Server

How can I write a query in SQL Server such as rank() but a bit different calculate.
For example rank is:
rankNumber uniqeId
1 160
2 159
3 158
4 157
5 156
5 156
7 152
8 151
8 151
10 150
I need the result like these:
rankNumber uniqeId
1 160
2 159
3 158
4 157
5 156
5 156
6 152
7 151
7 151
8 150
How can I do this? Is there such a function in SQL Server?
SELECT DENSE_RANK() OVER (ORDER BY TotCnt DESC) AS TopCustomers, CustomerID, TotCnt
FROM (SELECT CustomerID, COUNT(*) AS TotCnt
FROM Orders Group BY CustomerID) AS Cust
OUTPUT
To expand on the DENSE_RANK comment, the full query is short and sweet:
SELECT
DENSE_RANK() OVER (ORDER BY uniqueId DESC) AS rankNumber,
uniqueId
FROM myTable
ORDER BY rankNumber
There's a SQL Fiddle here

How to add summary rows to income statements in postgresql

Income statement table has structure:
sgroup char(30),
account char(10),
jan numeric(12,2),
feb numeric(12,2)
and has values:
SGroup Account Jan Feb
Sales 311 100 200
Sales 312 20 30
..
Other 410 3333 44
Other 411 333 344
...
How convert this table to have header and subtotals for each group:
Caption Jan Feb
Sales
311 100 200
312 20 30
Sales Total 120 230
Other
410 3333 44
411 333 344
Other total 3666 388
... ... ...
Grand Total ... ...
Caption column should contain group header, account numbers and group total for each group.
After total there should be empty row.
After that that there should be next group etc.
In the end there should be a "Grand Total" row containing the sum of all rows.
Using Postgres 9.1.2 in Debian.
Mono C# ASP.NET MVC application running in Debian. If it's more reasonable, this conversion can done in MVC controller also.
I would calculate sums per group in a CTE to use it three times in the main query:
WITH total AS (
SELECT sgroup, 'Sales Total'::text AS c, sum(jan) AS j, sum(feb) AS f
FROM income_statement
GROUP BY 1
)
( -- parens required
SELECT caption, jan, feb
FROM (
SELECT 1 AS rnk, sgroup, account::text AS caption, jan, feb
FROM income_statement
UNION ALL
SELECT 0 AS rnk, sgroup, sgroup::text, NULL, NULL FROM total
UNION ALL
SELECT 2 AS rnk, * FROM total
) sub
ORDER BY sgroup, rnk
)
UNION ALL
SELECT 'Grand Total', sum(j), sum(f) FROM total;
The extra set of parentheses is required to include ORDER BY.
You probably don't want to use the data type char(30):
Any downsides of using data type "text" for storing strings?

Latest Data based on DateTime or CustMCId

I have a table in which different Clients are assign to different MC. Like Client (84) switch the MC 3 times. Now I want to get the latest MC of Client=84. I make this Query
select max(cstmrMC.CustMCId),cstmrMC.CustId,cstmrMC.MCID,cstmrMC.AssignDate
from CustomerMC cstmrMC
where cstmrMC.CustId=84
group by cstmrMC.CustMCId,cstmrMC.CustId,cstmrMC.MCID,cstmrMC.AssignDate
ORDER BY cstmrMC.CustMCId,cstmrMC.CustId,cstmrMC.MCID,cstmrMC.AssignDate
which shows this result
CustMCId CustId MCID AssignDate
52 84 18 2013-10-01 18:21:56.000
59 84 7 2013-09-09 16:10:06.000
80 84 19 2013-10-09 03:54:00.000
156 84 21 2013-11-11 00:00:00.000
NOw I want only this
156 84 21 2013-11-11 00:00:00.000
How can I get this result????
Use the row_number function to partition and order the customers so that the most recent MCID (based on AssignDate) is first within each customer.
WITH cteCustomers AS (
SELECT CustMCId, CustId, MCID, AssignDate,
ROW_NUMBER() OVER(PARTITION BY CustId ORDER BY AssignDate DESC) AS RowNum
FROM CustomerMC
)
SELECT CustMCId, CustId, MCID, AssignDate
FROM cteCustomers
WHERE RowNum = 1;