I have a table with two columns, id and for each id an array with values. I want to calculate the moving avarage within the id over the moving 3 elements.
id
v
1
{210,200,180,120,150,200}
2
{230,180,140,100,170,210}
create table series(id int, v _int4);
insert into series
values(1,array[210,200,180,120,150,200])
,(2,array[230,180,140,100,170,210]);
If i use the following query it works for one id
select id, nr, "elemV", avg("elemV") over (order by nr rows between 3 PRECEDING AND CURRENT ROW) "movingAvgOver3elements"
from series t, unnest("v") with ordinality as a("elemV", nr)
where id = 1 ;
id
nr
elemV
movingAvgOverLast4Elements
1
1
210
210.0000000000000000
1
2
200
205.0000000000000000
1
3
180
196.6666666666666667
1
4
120
177.5000000000000000
1
5
150
162.5000000000000000
1
6
200
162.5000000000000000
How does it works for all id's within the id ?
The problem is in that case the 4 elements moving over the id 1 to 2
select id, nr, "elemV", avg("elemV") over (order by id, nr rows between 3 PRECEDING AND CURRENT ROW) "movingAvgOver3elements"
from series t, unnest("v") with ordinality as a("elemV", nr)
id
nr
elemV
movingAvgOver3elements
1
1
210
210.0000000000000000
1
2
200
205.0000000000000000
1
3
180
196.6666666666666667
1
4
120
177.5000000000000000
1
5
150
162.5000000000000000
1
6
200
162.5000000000000000
2
1
230
175.0000000000000000
2
2
180
190.0000000000000000
2
3
140
187.5000000000000000
2
4
100
162.5000000000000000
2
5
170
147.5000000000000000
2
6
210
155.0000000000000000
If I understand correctly, I think you just need to add a PARTITION BY clause to make each id a separate frame. With that clause in place, you can also remove the sort by id, although that's optional.
select id, nr, "elemV", avg("elemV") over (PARTITION BY id order by nr rows between 3 PRECEDING AND CURRENT ROW) "movingAvgOver3elements"
from series t, unnest("v") with ordinality as a("elemV", nr);
Related
I am working on a query for SQL Server 2005 that needs to return data with two 'index' fields. The first index 't_index' should increment every time the 'shade' column changes, whilst the second index increments within the partition of the values in the 'shade' column:
t_index s_index shade
1 1 A
1 2 A
1 3 A
1 4 A
1 5 A
2 1 B
2 2 B
2 3 B
2 4 B
2 5 B
To get the s_index column I am using the following:
Select ROW_NUMBER() OVER(PARTITION BY [shade] ORDER BY [shade]) as s_index
My question is how to get the first index to only increment when the value in the 'shade' column changes?
That can be accomplished with the DENSE_RANK() function:
DENSE_RANK() OVER(Order By [shade]) as t_index
You can try to use DENSE_RANK() for that:
SELECT
shade,
s_index = ROW_NUMBER() OVER(PARTITION BY [shade] ORDER BY [shade]),
t_index = DENSE_RANK() OVER (ORDER BY [shade])
FROM dbo.YourTableNameHEre
Gives output:
shade s_index t_index
A 1 1
A 2 1
A 3 1
A 4 1
A 5 1
B 1 2
B 2 2
B 3 2
B 4 2
B 5 2
ID
value
1
4
1
5
3
4
2
10
I want to add another column called count, that has for each id the number of observations.
Transformed table
id
value
count
1
4
2
1
5
2
3
4
1
2
10
1
You can use the OVER() clause to aggregate.
SELECT
ID,
value,
[count] = COUNT(*) OVER (PARTITION BY ID)
FROM dbo.TableName;
I have a table
WO# Seg# Part# QTY TotSale FlatSale
1 1 1 5 35 159
1 1 2 2 100 159
1 2 3 3 50 50
I need to calculate the FlatSale/SUM(TotSale) for each Seq# & WO# but do not group Seg# into one row.
I need this
WO# Seg# Part# QTY TotSale FlatSale Calc
1 1 1 5 35 159 1.177
1 1 2 2 100 159 1.177
1 2 3 3 50 50 1
With my code I am able to only do the division on each individual line like this:
select *, FlatSale/TotSale as Calc from table
WO# Seg# Part# QTY TotSale FlatSale Calc
1 1 1 5 35 159 4.54
1 1 2 2 100 159 1.59
1 2 3 3 50 50 1
I wouldn't mind leaving my Calc column and adding another column if that's the easiest way to do it.
Maybe something like this:
SELECT
[WO#],[Seg#],[Part#],[QTY],[TotSale],[FlatSale]
((FlatSale*100)/(SUM([TotSale]) OVER(PARTITION BY [Seg#] ORDER BY [Seg#])))/100 AS Calc
FROM SomeTable
You can use a lateral join. Here's something quick (not tested as I don't have access to mssql at the moment):
select *, x.CalcPrice as Calc
from table t
outer apply (
select t.FlatSale/SUM(ix.TotSale) CalcPrice
from table ix where ix.[WO#] = t.[WO#]
and ix.[Seg#] = t.[Seg#]) x
Something like that.
I have a table that looks as follows
Amount Factor Month Customer
1 1 2 A
3 1 2 A
4 -1 2 A
2 1 2 B
2 1 2 B
3 -1 2 B
4 1 3 A
5 1 3 A
6 -1 3 A
I want to aggregate (sum) the column Amount per Month and Customer. The Amounts should be multiplied with the value in the column Factor.
Hence, the result should look as follows (could be an UPDATE to the same table or a new table):
Amount Factor Month Customer
0 1 2 A
1 1 2 B
3 1 3 A
Try below
SELECT SUM(Amount * Factor) as Amount,Month,Customer
FROM tableName
GROUP BY Month,Customer
I think this is what you want:
select month, customer, sum(amount * factor) as sum_amount
from t
group by month, customer;
I'm not sure why you would want factor in the result set.
Here is my problem: I have a list of flagged values, I want to see where those values would be in the case they weren't flagged. But I don't want the other flagged values to influence the order.
Note: Flagged values are the ones with CurrentPlace 10000
ID Value CurrentPlace
------------------------
1 2 1
2 8 3
3 3 2
4 4 10000
5 5 10000
6 10 10000
Using:
select *
from
(select
id, value,
rank() over (order by Value asc) as Rank
from
tbl1) r
where
r.ID in (select id from tbl1 where CurrentPlace = 10000)
Desired output:
ID Value Rank
------------------
4 4 3
5 5 3
6 10 4
But I'm getting this instead:
ID Value Rank
------------------
4 4 3
5 5 4
6 10 6
Any help will be appreciated
Thank you guys
I've solved with
SELECT ID, Value, Rank
FROM tbl1 a
CROSS APPLY
(SELECT isnull(max(currentPlace),0) + 1 AS Rank FROM tbl1 WHERE value < a.value and currentPlace <> 10000) b
WHERE a.CurrentPlace = 10000
Please feel free to comment this out.