简体   繁体   中英

SQL Calculated Column based on OVER PARTITION BY Clause

I have a view with a ROW NUMBER based on a PARTITION BY across some columns. The ROW NUMBER starts at 0 and increments for each record based on ssis inputs from various files, for each file with a unique filename and date combination, there will be row numbers from 0 - n.

Now i need to do create a new column that does a calculation on a value, using the row number.

RowNumber Value Filename FileDate  
0           500   datax   20200301  
1           200   datax   20200301  
2           100   datax   20200301  
0           600   datax   20200302  
1           200   datax   20200302  
2           200   datax   20200302  
3           100   datax   20200302  
4           200   datax   20200302  
0           700   datay   20200303  
1           500   datay   20200303 

I want a new column that divides the values from each RowNumber n by the value in RowNumber 0, for its unique partition

NEWVALUE = (Value @ RowNumber N / Value at RowNumber 0)

RowNumber Value  NEWVALUE          Filename FileDate  
0           500   NULL             datax   20200301  
1           200   0.400            datax   20200301  
2           100   0.200            datax   20200301  
0           600   NULL             datax   20200302  
1           200   0.333            datax   20200302  
2           200   0.333            datax   20200302  
3           100   0.167            datax   20200302  
4           300   0.500            datax   20200302  
0           700   NULL             datay   20200303  
1           500   0.714            datay   20200303  

Anyone know how to do this

Like others have suggested ROWNUM = 0 is equivalent of FIRST_VALUE

The tricky bit is adding a null for NEWVALUE instead of 1, you will have to resort to a subquery.

SELECT 
RowNumber,Value,CASE WHEN RowNumber=0 THEN NULL else NEWVALUE end as NEWVALUE, FileName,FileDate
FROM (
  select ROW_NUMBER() OVER (PArtition BY FileDate ORDER BY Value DESC) -1 as RowNumber,
  Value,
  Value * 1.0 / FIRST_VALUE(Value) OVER (PArtition BY FileDate ORDER BY Value DESC) as NEWVALUE
  ,FileName
  ,FileDate
  from Data
  ) t

Here's the sqlfiddle if you would like to play around with it http://sqlfiddle.com/#!18/2bdca4/1

One method uses conditional aggregation:

select ( value * 1.0 /
         max(case when rownumber = 0 then value end) over (partition by filename, filedate)
         value
       ) as ratio

I am guessing that the partitioning groups are based on filename and filegroup .

Or use first_value() :

select ( value * 1.0 /
         first_value(value) over (partition by filename, filedate order by rownumber)
         value
       ) as ratio

To put either of these into the view, you'll need a subquery.

If the ordering is based on the maximum value, then you can use similar logic (and dispense with the subquery):

select ( value * 1.0 /
         max(value) over (partition by filename, filedate)  * 1.0
         value
       ) as ratio

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM