Subtract from previous row based on certain rows - sql

I have a table like this in SQL
I want to calculate the demand column just like the demand column I created in Excel.
This is the formula I used in Excel
=IF(T2=T1,IF(V1>V2,V1-V2,0),0)
This formula checks if the product type is of the same category and if yes, calculates the number of products that were taken by substracting the stock amount from the previous timestamp.
I want to implement the same in Microsoft SQL Server. Any help will be appreciated.

You can use:
select t.*,
(case when lag(stock) over (partition by type order by time) > stock
then lag(stock) over (partition by type order by time) - stock
else 0
end)
from t;

Related

SQL calculating running total as you go down the rows but also taking other fields into account

I'm hoping you guys can help with this problem.
I have a set of data which I have displayed via excel.
I'm trying to work out the rolling new cap allowance but need to deduct from previous weeks bookings. I don't want to use a cursor so can anyone help.
I'm going to group by the product id so it will need to start afresh for every product.
In the image, Columns A to D are fixed and I am trying to calculate the data in column E ('New Cap'). The 'New Cap' is the expected results.
Column F gives a detailed formula of what im trying to do.
Not sure what I've done for the post to be marked down.
Thanks
Update:
The formula looks like this.
You want the sum of the cap through this row minus the sum of booked through the previous row. This is easy to do with window functions:
select t.*,
(sum(cap + booked) over (partition by productid order by weekbeg) - booked
) as new_cap
from t;
You can get the new running total using lag and sum over window functions - calculate the cap-booked first, then use sum over() for the running total:
select weekbeg, ProductId, Cap, Booked,
Sum(n) over(partition by productid order by weekbeg) New_Cap
from (
select *, cap - Lag(booked,1,0) over(partition by productid order by weekbeg)n
from t
)t

Oracle SQL - Sum next X number of Rows

I have a table in Oracle database whith projected sales per week and would like to sum the next 3 weeks for each week. Here is an example of the table for one product and what I would like to achieve in the last column.
I tried the Sum(Proj Sales) over (partition by Product order by Date), but I am not sure how to configure the Sum Over to get what I am looking for.
Any assistance will be much appreciated.
You can use analytic functions. Assuming that the next three weeks are the current row and the next two:
select t.*,
sum(proj_sales) over (partition by product
order by date
rows between current row and 2 following
) as next_three_weeks
from t;

Interesting logic to be solved in teradata SQL

In the image the target is top calculate years since last DX.
A year level we want to calculate thw number of years since we have found a DX.
Eg
There was a dx for id 1 in 2014 so in 2015,2016 and 2017 we are populating the value in incremental manner of year.
we find one more DX in 2017 so in the following year we populate 1.
the same cycle beging in next ID
The Idea is to implement this logic in Teradata SQL
Can someone help how this could be done?
You can get the largest value for the most recent "DX" value using analytic functions:
select t.*,
max(case when code = 'DX' then date end) over
(partition by id
order by date
range between unbounded preceding and 1 preceding
) as prev_dx
from t;
I have no idea how to convert this to "years". The date format makes no sense to me.

Use row number in aggregate sum over UNBOUNDED FOLLOWING SQL

I would like to add a discount rate when summing Cashflows over a number of period. To do this I need to multiply each of the remaining cashflows by the discount rate, consummate with this period. I could do this, if I knew the row number of each period, but I can't use it with the window calc I am using. The example below shows the column 'Remaining Interest' which is what I am trying to calculate based on raw data of period and interest.
select Period,RemainingInterest = SUM(PeriodInterestPaid)
OVER (PARTITION BY Name ORDER BY period ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
FROM CF A
Period Interest Remaining Interest(Query) Remaining Interest(Required)
1 1000 1000+2000 1000/1.02^1+2000/1.02^2
2 2000 2000 2000/1.02^1
hi i hope i understand Well ---
you need to get the sum of value based on the period that what i under stand from the query but u said that you need a multiply
So there's no need to make a window function just group by
select Period, SUM(PeriodInterestPaid) as RemainingInterest
FROM CF A
and if u want a multiplay you will make group by also but u will use anther exp :
Pls explan what exactly u need

SQL code for time and record specific selection?

I've been troubling my brain about the next problem. I work with a large dataset which contains records of species observations and location. Here's what I want to do:
For each period of time (5 years) I want to know the number of distinct species that were described in that particular period, but which were not described in an earlier period. So for each new period, the query needs to check if a certain species wasn't already described before. This needs to be done for 100 separate areas. The dataset already knows for each record in which 5 year period it was recorded.
My final result should be a table with areas on the x-axis, the periods on the y-axis, and in the cells the number of described species for each period, per area. It would be great if this is possible with one query. But I'm planning to do this in Excel, since I would be very happy to get for each area, the number of distinct species per time period.
PostgreSQL supports Windowed Aggregate Functions:
SELECT
area, period, SUM(x) AS newSpecies
FROM
(
SELECT area, period,
CASE -- check for the first description
WHEN date_col = MIN(date_col) OVER (PARTITION BY species) THEN 1
ELSE 0
END AS x
FROM au.trans
) AS dt
GROUP BY area, period
Depending on your data you might need to switch to ROW_NUMBER instead:
CASE -- check for the first description
WHEN ROW_NUMBER() OVER (PARTITION BY species ORDER BY date_col) = 1 THEN 1
ELSE 0
END AS x
Now you just have to pivot that data, don't know if there's a PIVOT function in PostgreSQL, otherwise you'll need to do the classical MAX(CASE). For each area you need to add a
SELECT period,
-- cut&paste&modify for each area
MAX(CASE WHEN area = 'area52' THEN newSpecies ELSE 0 END AS area52,
....
FROM (previous query) AS dt
GROUP BY period