Teradata - Lag column and UNBOUNDED PRECEDING - sql

suppose I have the following table in teradata sql.
How do I get the 'final' column.
The first value is equal to the 'mount' column, the second is equal to final - price (10-1), and the third is equal (9-2).
hour mount price
0 10 1
1 10 2
2 10 3
hour mount price final
0 10 1 10
1 10 2 9
2 10 3 7

You seem to want a cumulative sum -- and then the difference from mount:
select hour, mount price,
(mount + price -
sum(price) over (order by hour rows between unbounded preceding and current row)
) as final
from t;
You really want the sum up to the preceding row. But if you use:
sum(price) over (order by hour rows between unbounded preceding and 1 preceding)
then you will need to deal with NULL values. Instead, I just add price in from the current row and then let the cumulative sum include that price.

Related

Sum previous row values in same table

I try to sum value in pervious rows, I want to sum the pervious quantity "Stock on hand" and put the result in each row, example
ItemID
Qty
Stockon Hand ( the result updated in this column)
1000
1
1
1000
5
6 ( sum qty previous in pervious row plus the qty in the current row)
1000
2
8 ( sum qty previous in pervious row plus the qty in the current row)
1000
1
9 ( sum qty previous in pervious row plus the qty in the current row)
How can I update the column "Stock on hand" by summing the qty in the current row and previous rows?
select ItemID, Qty
, sum(qty) over (order by itemid rows between 1 preceding and 1 preceding) as previous_Qty
from #Stock
order by itemid
Here is a working example. Note, I took the liberty of adding an column for a proper sequence... ID, but you could use a date column as well
You may also notice that I added partition by ItemID
Declare #YourTable Table ([ID] int,[ItemID] int,[Qty] int)
Insert Into #YourTable Values
(1,1000,1)
,(2,1000,5)
,(3,1000,2)
,(4,1000,1)
Select *
,OnHand = sum(Qty) over (partition by ItemID order by ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
from #YourTable
Results
ID ItemID Qty OnHand
1 1000 1 1
2 1000 5 6
3 1000 2 8
4 1000 1 9

Incremental sum in Oracle SQL using analytic functions

How can I sum values per record from a table?
If I have
row
key
value
expected
row 1
A
1
1
row 2
A
5
6
row 3
B
10
10
row 4
B
1
11
row 5
B
1
12
can you point me some directions?
thanks
You can use Windowing Functions
Something like
select t.*,
sum(value) over (partition by key order by "row" rows unbounded preceding) expected
from tab t;
Note that ROW is a reserved word. You can create a table with a column row, but you better use another name.

SQLite - Rolling Average/Sum

I have a dataset as shown below, wondering how I can do a rolling average with its current record followed by next two records. Example: lets consider the first record whose total is 3 followed by 4 and 7 ,Now the rolling 3 day average for first record would be 4.6 and so on.
Date Total
1 3
2 4
3 7
4 1
5 2
6 4
Expected output:
Date Total 3day_rolling_Avg
1 3 4.6
2 4 4
3 7 3.3
4 1 2.3
5 2 null
6 4 null
PS: Having "null" value isn't important. This is just a sample data where I need to look at more than 3 days(Ex: 30 days rolling)
I think that the simplest approach is a window avg(), with the poper window frame:
select
t.*,
avg(total)
over(order by date rows between current row and 2 following) as "3d_rolling_avg"
from mytable t
If you want to return a null value when there is less than 2 leading rows, as show in your expected results, then you can use row_number() on top of it:
select
t.*,
case when rank() over(order by date desc) <= 2
then avg(total)
over(order by date rows between current row and 2 following)
end as "3d_rolling_avg"
from mytable t

Calculate moving average with null values

I have a school graduation data set by year and subgroup and have been provided the numerator and denominator and the single year graduation rate but I also need to calculate a 3 year moving average. I was advised by a statistician that no longer works with us that to do this I needed to get the running total for the numerator for 3 years and the running total for 3 years for the denominator. I understand the math behind it and have checked my work by hand and via excel with a few subgroups. I have also calculated this using T-SQL with no problem so long as there are no null records but I’m struggling with the calculation when there are nulls or 0.
I have tried running the query accounting for null by using NULLIF
ID,
Bldg,
GradClass,
Sbgrp ,
TGrads,
TStus,
Rate,
/*Numerator Running total*/
SUM (TGrads) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) AS NumSum,
/*Denominator Running Total*/
SUM ( TStus) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) AS DenSum,
/*Moving Year Average*/
(
( SUM ( TGrads) OVER ( partition BY DistrictID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) ) / NULLIF ( ( SUM ( TStus) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) ), 0 ) * 100
) AS 3yrAvg
FROM
KResults.DGSRGradBldg
First question, I was provided a record for all subgroups even if they didn’t have students in the subgroup. I want to keep the record so that all subgroups are accounted for within the district and since I know that they didn’t have data, can I substitute the Null values in Tgrads, TStus with a 0? If I do substitute those values with a 0 how can I show the rate as null?
Second question how can I compute the rate with either a null or 0 denominator? I understand you can’t divide by 0 but I want to maintain the record so it’s easy and clear to see that they had no data. How can I do this? When I try to calculate this without accounting for Null I get errors, 1.)Divide by zero error encountered. (8134) and 2.) Null value is eliminated by an aggregate or other SET operation. (8153).
Knowing I can’t divide by 0 or Null I modified my query to include NULLIF and when I do that the query runs with no errors but I don’t get accurate percentage for rates that are below 100%. All my rates are now either 100% or 0 - note the last row, the moving average of 2/3 is not 0.
Here’s what the data looks like if I try to account for nulls my Moving three year average shows as 0. Note the Moving three year Avg Column shows all 0.
ID Bldg Class Sbggrp TGrads TStus Rate NumSum DenSum 3yrAvg
A 1 2014 A1 46 49 93.9 46 49 0
A 1 2015 A1 41 46 89.1 87 95 0
A 1 2016 A1 47 49 95.9 134 144 0
A 1 2017 A1 38 40 95.0 126 135 0
A 1 2018 A1 59 59 98.3 143 148 0
A 1 2014 A2 1 1 100 1 1 100
A 1 2015 A2 1 1 100
A 1 2016 A2 1 1 100
A 1 2017 A2 2 3 66.7 2 3 0
A 1 2018 A2 2 2 100 4 5 0
Any advice would be appreciated but please provide suggestions kindly to this newbie.
Thanks for your time and help.
Answer to question 1: put in the select condition
ISNULL(TGrads,0) AS TGRADS,
ISNULL(TStus,0) AS TSTUS,
Answer to question 2: I'd do this
(CASE WHEN SUM(TStus) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) IS NOT NULL
AND SUM(TStus) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) <>0
THEN (SUM(TGrads) OVER ( partition BY DistrictID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) / (SUM(TStus) OVER ( partition BY ID, Sbgrp ORDER BY GradClass ROWS BETWEEN 2 preceding AND CURRENT row ) ) ) * 100
ELSE NULL END
) AS 3yrAvg
I put null after "ELSE"...You can choose your default value.

Postgres get first and last version for individual vendor

I have mapping table for RFQ(request for quotation) and Vendor's bid amount with version.
Table :
id rfq_id(FK) vendor_id(FK) amount version
-----------------------------------------------
1 1 1 100 1
2 1 1 90 2
3 1 1 80 3
4 1 2 50 1
5 1 7 500 1
6 1 7 495 2
7 1 7 500 3
8 1 7 525 4
9 1 7 450 5
10 1 7 430 6
11 2 1 200 1
12 2 2 300 1
13 2 2 350 2
14 2 3 40 1
15 3 4 70 1
In above table, I want analysis for vendor's first and last bid for particular rfq_id.
Expected Output for rfq_id=1 :
vendor_id first_bid last_bid
---------------------------------
1 100 80
2 50 50
7 500 430
From Postgres : get min and max rows count in many to many relation table I have came to know about window and partition. So I have tried below query.
SELECT
vendor_id,
version,
amount,
first_value(amount) over w as first_bid,
last_value(amount) over w as last_bid,
row_number() over w as rn
FROM
rfq_vendor_version_mapping
where
rfq_id=1
WINDOW w AS (PARTITION BY vendor_id order by version)
ORDER by vendor_id;
With above query, every vendor's maximum rn is my output.
http://sqlfiddle.com/#!15/f19a0/7
Window functions add columns to all the existing rows, instead of grouping input rows into a single output row. Since you are only interested in the bid values, use a DISTINCT clause on the fields of interest.
Note that you need a frame clause for the WINDOW definition to make sure that all rows in the partition are considered. By default, the frame in the partition (the rows that are being used in calculations) runs from the beginning of the partition to the current row. Therefore, the last_value() window function always returns the value of the current row; use a frame of UNBOUNDED PRECEDING TO UNBOUNDED FOLLOWING to extend the frame to the entire partition.
SELECT DISTINCT
vendor_id,
version,
amount,
first_value(amount) OVER w AS first_bid,
last_value(amount) OVER w AS last_bid
row_number() over w as rn
FROM
rfq_vendor_version_mapping
WHERE rfq_id = 1
WINDOW w AS (PARTITION BY vendor_id ORDER BY version
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
ORDER BY vendor_id;
You have to GROUP BY vendor_id because you want just one row per vendor_id:
SELECT
vendor_id,
MAX(CASE WHEN rn = 1 THEN amount END) AS first_bid,
MAX(CASE WHEN rn2 = 1 THEN amount END) AS last_bid
FROM (
SELECT
vendor_id,
version,
amount,
row_number() over (PARTITION BY vendor_id order BY version) as rn,
row_number() over (PARTITION BY vendor_id order BY version DESC) as rn2
FROM
rfq_vendor_version_mapping
WHERE
rfq_id=1) AS t
GROUP BY vendor_id
ORDER by vendor_id;
The query uses conditional aggregation in order to extract amount values that correspond to first and last bid.
Demo here
Without ORDER BY OLAP-functions default to ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING but with ORDER BY this changes to ROW UNBOUNDED PRECEDING.
You were quite close, but you need two different windows:
select vendor_id, amount as first_bid, last_bid
from
(
SELECT
vendor_id,
version,
amount,
last_value(amount) -- highest version's bid
over (PARTITION BY vendor_id
order by version
rows between unbiunded preceding and unbounded following) as last_bid,
row_number()
over (PARTITION BY vendor_id
order by version) as rn
FROM
rfq_vendor_version_mapping
where
rfq_id=1
) as dt
where rn = 1 -- row with first version/bid
ORDER by vendor_id;