Currently I have this table in sql database sorted by Account#.
Account# Charge_code PostingDate Balance
12345 35 1/18/2016 100
**12345 35 1/20/2016 200**
12345 61 1/23/2016 250
12345 61 1/22/2016 300
12222 41 1/20/2016 200
**12222 41 1/21/2016 250**
12222 42 1/23/2016 100
12222 42 1/25/2016 600
How do I select last row prior to the change in the charge_code column for each Account#. I highlighted the rows that I am trying to return.
The query should execute quickly with the table having tens of thousands of records.
In SQL Server 2012+, you would use lead():
select t.*
from (select t.*,
lead(charge_code) over (partition by account order by postingdate) as next_charge_code
from t
) t
where charge_code <> next_charge_code;
In earlier versions of SQL Server, you can do something similar with apply.
Related
I have the following View in PostgreSQL:
idshipment idorder quantity_order date quantity_in_shipment percent_sent
50 1 1020 1.1.16 432 42
51 1 1020 17.1.16 299 71
51 1 1020 20.1.16 144 85
51 1 1020 45.1.16 145 100
52 2 1 3.1.17 5 100
This View shows shipments per order.
For example:
idorder=1 was sent by 4 shipments:
quantity in first shipment is 432 which means 42% of order was sent
quantity in second shipment is 299 which means 71% of order was sent
quantity in third shipment is 144 which means 85% of order was sent
quantity in forth shipment is 145 which means 100% of order was sent
I need a query which will show me the first date where each order was sent above 75%. meaning each order shows only one row.
For the above data I should see:
idorder date
1 20.1.16 (cause its 85% first time above 75%)
2 3.1.17 (cause its 100% first time above 75%)
How can i do that?
You can use distinct on:
select distinct on (t.idshipment) t.*
from t
where t.percent_sent >= 75
order by t.idshipment, t.percent_sent asc;
Try something like this:
SELECT iorder, MIN("date") AS "date"
FROM your_view
WHERE percent_sent >= 75
GROUP BY iorder
use group by to get only one record per idorder and MIN() to aggregate date by selecting the earliest date
I created a table call shipment that has data like you provided:
and execute this query
SELECT s.idorder, MIN(s.date) as date
FROM shipment s
WHERE percent_sent >= 75
GROUP BY s.idorder
result:
idorder date
----------- ----------
1 2016-01-20
2 2017-03-01
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
I have a requirement to calculate rolling compound interest on several accounts in pl/sql. I was looking for help/advice on how to script calculate these calculations. The calculations I need are in the last two columns of the output below (INTERESTAMOUNT AND RUNNING TOTAL). I found similar examples of this on here, but nothing specifically fitting these requirements in pl/sql. I am also new to CTE/Recursive Techniques and the Model technique I found required a specific iteration which would be variable in this case. Please see my problem below:
Calculations:
INTERESTAMOUNT = (Previous Year RUNNING TOTAL+ Current Year AMOUNT) * INTEREST_RATE
RUNNINGTOTAL = (Previous Year RUNNING TOTAL+ Current Year AMOUNT) * (1 + INTEREST_RATE) - CURRENT YEAR EXPENSES
Input Table:
YEAR ACCT_ID AMOUNT INTEREST_RATE EXPENSES
2002 1 1000 0.05315 70
2003 1 1500 0.04213 80
2004 1 800 0.03215 75
2005 1 950 0.02563 78
2000 2 750 0.07532 79
2001 2 600 0.06251 75
2002 2 300 0.05315 70
Desired Output:
YEAR ACCT_ID AMOUNT INTEREST_RATE EXPENSES INTERESTAMOUNT RUNNINGTOTAL
2002 1 1000 0.05315 70 53.15 983.15
2003 1 1500 0.04213 80 104.62 2507.77
2004 1 800 0.03215 75 106.34 3339.11
2005 1 950 0.02563 78 109.93 4321.04
2000 2 750 0.07532 79 56.49 727.49
2001 2 600 0.06251 75 82.98 1335.47
2002 2 300 0.05315 70 86.93 1652.4
One way to do it is with a recursive cte.
with rownums as (select t.*
,row_number() over(partition by acct_id order by yr) as rn
from t) -- t is your tablename
,cte(rn,yr,acct_id,amount,interest_rate,expenses,running_total,interest_amount) as
(select rn,yr,acct_id,amount,interest_rate,expenses
,(amount*(1+interest_rate))-expenses
,amount*interest_rate
from rownums
where rn=1
union all
select t.rn,t.yr,t.acct_id,t.amount,t.interest_rate,t.expenses
,((c.running_total+t.amount)*(1+t.interest_rate))-t.expenses
,(c.running_total+t.amount)*t.interest_rate
from cte c
join rownums t on t.acct_id=c.acct_id and t.rn=c.rn+1
)
select * from cte
Sample Demo
Generate row numbers using row_number function
Calculate the interest and running total of the first row for each acct_id (anchor in the recursive cte).
Join every row to the next one (ordered by ascending order of year column) for each account_id and compute the running total and interest for the subsequent rows.
I've this table with the following data
user Date Dist Start
1 2014-09-03 150 12500
1 2014-09-04 220 null
1 2014-09-05 100 null
2 2014-09-03 290 18000
2 2014-09-04 90 null
2 2014-09-05 170 null
Based on the value in Start Column i need to add another column and repeat the value if not null for the same user
The resultant table should be as below
user Date Dist Start StartR
1 2014-09-03 150 12500 12500
1 2014-09-04 220 null 12500
1 2014-09-05 100 null 12500
2 2014-09-03 290 18000 18000
2 2014-09-04 90 null 18000
2 2014-09-05 170 null 18000
Can someone please help me out with this query? because i don't have any idea how can i do it
For the data you have, you can use a window function:
select t.*, min(t.start) over (partition by user) as StartR
from table t
You can readily update using the same idea:
with toupdate as (
select t.*, min(t.start) over (partition by user) as new_StartR
from table t
)
update toupdate
set StartR = new_StartR;
Note: this works for the data in the question and how you have phrased the question. It would not work if there were multiple Start values for a given user, or if there were NULL values that you wanted to keep before the first non-NULL Start value.
You can use COALESCE/ISNULL and a correlated sub-query:
SELECT [user], [Date], [Dist], [Start],
StartR = ISNULL([Start], (SELECT MIN([Start])
FROM dbo.TableName t2
WHERE t.[User] = t2.[User]
AND t2.[Start] IS NOT NULL))
FROM dbo.TableName t
I have used MIN([Start]) since you haven't said what should happen if there are multiple Start values for one user that are not NULL.
This question is probably answered before but i cant find how to get the latest records of the months.
The problem is that I have a table with sometimes 2 row for the same month. I cant use the aggregate function(I guess) cause in the 2 rows, i have different data where i need to get the latest.
Example:
name Date nuA nuB nuC nuD
test1 05/06/2013 356 654 3957 7033
test1 05/26/2013 113 237 399 853
test3 06/06/2013 145 247 68 218
test4 06/22/2013 37 37 6 25
test4 06/27/2013 50 76 20 84
test4 05/15/2013 34 43 34 54
I need to get a result like:
test1 05/26/2013 113 237 399 853
test3 06/06/2013 145 247 68 218
test4 05/15/2013 34 43 34 54
test4 06/27/2013 50 76 20 84
** in my example the data is in order but in my real table the data is not in order.
For now i have something like:
SELECT Name, max(DATE) , nuA,nuB,nuC,nuD
FROM tableA INNER JOIN
Group By Name, nuA,nuB,nuC,nuD
But it didn't work as i want.
Thanks in advance
Edit1:
It seems that i wasn't clear with my question...
So i add some data in my example to show you how i need to do it.
Thanks guys
Use SQL Server ranking functions.
select name, Date, nuA, nuB, nuC, nuD from
(Select *, row_number() over (partition by name, datepart(year, Date),
datepart(month, Date) order by Date desc) as ranker from Table
) Z
where ranker = 1
Try this
SELECT t1.* FROM Table1 t1
INNER JOIN
(
SELECT [name],MAX([date]) as [date] FROM Table1
GROUP BY [name],YEAR([date]),MONTH([date])
) t2
ON t1.[date]=t2.[date] and t1.[name]=t2.[name]
ORDER BY t1.[name]
Can you not just do an order
select * from tablename where Date = (select max(Date) from tablename)
followed by only pulling the first 3?