Partition Over Clause with start and stop - sql

I have a set of data where value is calculated starting from 1 - 12 then moves 1 step down and calculates another 1 - 12. This works well in Excel however how do I achieve this in SQL.
Is it even possible?
I have tried
ROW_COUNT = ROW_NUMBER()OVER(PARTITION BY StudioMain ORDER BY Finperiod ASC)/13+1,
which gives me a list of numbers then restarts after 12
so I want to sum rows 1-12 then I want to sum rows 1-12 but starting at row 2 ending at row 13
then sum rows 1-12 starting at row 3 ending at row 14
How do I sum row 1 12 then restart sum 1-12 but from row 2?

It looks like you want a window sum with a row frame:
select
t.*,
Debtors / sum(GrossSales) over(
partition by StudioMain
order by Finperiod
rows between 11 preceding and current row
) DeptorDays
from mytable t
order by StudioMain, FinPeriod
If you want no results for the 11 first rows, as shown in your image, you can wrap the sum() in a conditional expression:
select
t.*,
case when row_number() over(partition by StudioMain order by Finperiod) >= 12
then Debtors / sum(GrossSales) over(
partition by StudioMain
order by Finperiod
rows between 11 preceding and current row
)
end DeptorDays
from mytable t
order by StudioMain, FinPeriod

Related

RANK() function with over is creating ranks dynamically for every run

I am creating ranks for partitions of my table. Partitions are performed by name column with ordered by its transaction value. While I am generating these partitions and checking count for each of the ranks, I get different number in each rank for every query run I do.
select count(*) FROM (
--
-- Sort and ranks the element of RFM
--
SELECT
*,
RANK() OVER (PARTITION BY name ORDER BY date_since_last_trans desc) AS rfmrank_r,
FROM (
SELECT
name,
id_customer,
cust_age,
gender,
DATE_DIFF(entity_max_date, customer_max_date, DAY ) AS date_since_last_trans,
txncnt,
txnval,
txnval / txncnt AS avg_txnval
FROM
(
SELECT
name,
id_customer,
MAX(cust_age) AS cust_age,
COALESCE(APPROX_TOP_COUNT(cust_gender,1)[OFFSET(0)].VALUE, MAX(cust_gender)) AS gender,
MAX(date_date) AS customer_max_date,
(SELECT MAX(date_date) FROM xxxxx) AS entity_max_date,
COUNT(purchase_amount) AS txncnt,
SUM(purchase_amount) AS txnval
FROM
xxxxx
WHERE
date_date > (
SELECT
DATE_SUB(MAX(date_date), INTERVAL 24 MONTH) AS max_date
FROM
xxxxx)
AND cust_age >= 15
AND cust_gender IN ('M','F')
GROUP BY
name,
id_customer
)
)
)
group by rfmrank_r
For 1st run I am getting
Row f0
1 3970
2 3017
3 2116
4 2118
For 2nd run I am getting
Row f0
1 4060
2 3233
3 2260
4 2145
What can be done, If I need to get same number of partitions getting ranked same for each run
Edit:
Sorry for the blurring of fields
This is the output of field ```query to get this column````
The RANK window function determines the rank of a value in a group of values.
Each value is ranked within its partition. Rows with equal values for the ranking criteria receive the same rank. Drill adds the number of tied rows to the tied rank to calculate the next rank and thus the ranks might not be consecutive numbers.
For example, if two rows are ranked 1, the next rank is 3.

SSRS sum values based on row number

I would like to get the sum of all values in a column IF they have a rowNumber greater than the current row
so if i have 4 rows:
Row 1 would be the sum of rows 2,3 and 4
Row 2 would be the sum of rows 3 and 4
Row 3 would be the value of row 4
Row 4 would be 0
This is the query I currently have:
SELECT
no_,
name AS member,
amount,
effective,
balance
FROM c
WHERE
status != 'closed'
AND amount != 0.00
ORDER BY no_, effective
In my ssrs table I'm using the expression RowNumber("member") to assign row numbers for each row per member
You would seem to want a cumulative sum in reverse order, excluding the current value. I would express this as:
select sum(val) over (order by rownum desc) - val
I am clear how this relates to your query.
You can also express this using a window frame:
select sum(val) over (order by rownum rows between 1 following and unlimited following)
The only difference is that this would return NULL for the last row rather than 0.

select record from filtered results in postgreSQL

I have a function which gives me ordered rows (the function already order by the results):
By doing : select * from func1(ID)
Example A:
rownum date qty
1 1.1.10 -5
2 1.10.10 6
3 2.10.10 6
4 5.10.10 -2
5 6.10.10 -8
Example B:
rownum date qty
1 1.1.10 -7
2 1.10.10 6
Note: rownum is a column i calculate manually in my function. It's order is exact to my needs. So it's ok to be based on that.
I want to write a query which pass over the rows from bottom to top (highest rownum till lowest rownum) and return the date of the first encountered row that has negative qty
For example A the returned value is 6.10.10 (rownum 5 is the first row with negative value of qty)
for example B 1.1.10 (rownum 2 is the first row with negative value of qty)
How can I do that?
You could use ROW_NUMBER:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY rownum DESC) as rn
FROM func1(ID)
WHERE qty < 0
)
SELECT *
FROM cte
WHERE rn = 1;
I don't believe that table-valued functions in Postgres guarantee the ordering of the results. You will need to use an order by or some other mechanism.
If you want the most recent date with a negative value:
select max(date)
from func1(ID) t
where qty < 0;
If you have another ordering in mind:
select date
from func1(ID) t
where qty < 0
order by rownum desc -- your order by conditions here, but inverted
fetch first 1 row only;
This will allow you to fetch other values from the row, if you like.

Find average in postgresql

In my table I am having say 5 numbers. I want to find moving average of 3 numbers.
Query I am using is
select avg(value) over(order by value rows between 3 preceding and 1 preceding) as average
from test;
I want my query to start finding average from 4th value as first three values will not be having 3 previous values to calculate from. Please suggest.
The average will work for the first three -- it will just either be NULL or based on fewer than 3 rows.
But, you can do what you want using row_number();
select (case when row_number() over (order by value) > 3
then avg(value) over (order by value rows between 3 preceding and 1 preceding)
end) as average
from test;

Multiple filters on SQL query

I have been reading many topics about filtering SQL queries, but none seems to apply to my case, so I'm in need of a bit of help. I have the following data on a SQL table.
Date item quantity moved quantity in stock sequence
13-03-2012 16:51:00 xpto 2 2 1
13-03-2012 16:51:00 xpto -2 0 2
21-03-2012 15:31:21 zyx 4 6 1
21-03-2012 16:20:11 zyx 6 12 2
22-03-2012 12:51:12 zyx -3 9 1
So this is quantities moved in the warehouse, and the problem is on the first two rows which was a reception and return at the same time, because I'm trying to make a query which gives me the stock at a given time of all items. I use max(date) but i don't get the right quantity on result.
SELECT item, qty_in_stock
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY item ORDER BY item_date DESC, sequence DESC) rn
FROM mytable
WHERE item_date <= #date_of_stock
) q
WHERE rn = 1
If you are on SQL-Server 2012, these are several nice features added.
You can use the LAST_VALUE - or the FIRST_VALUE() - function, in combination with a ROWS or RANGE window frame (see OVER clause):
SELECT DISTINCT
item,
LAST_VALUE(quantity_in_stock) OVER (PARTITION BY item
ORDER BY date, sequence
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING)
AS quantity_in_stock
FROM tableX
WHERE date <= #date_of_stock
Add a where clause and do the summation:
select item, sum([quantity moved])
from t
group by item
where t.date <= #DESIREDDATETIME
If you put a date in for the desired datetime, remember that goes to midnight when the day starts.