Select rows based on grouped rolling sum condition in Oracle SQL - sql

I have a table like the one below:
ID
RID
Count
1
1
1
2
1
3
3
1
5
4
1
1
5
2
1
6
2
6
7
2
3
8
2
2
9
2
4
I am trying to retrieve the rows of each RID until the rolling sum of Count is ≤ 10.
In this example I need all rows of RID = 1 and only rows 1, 2 and 3 of RID = 2.
Expected answer:
ID
RID
Count
Sum_Count
1
1
1
NULL
2
1
3
4
3
1
5
9
4
1
1
10
5
2
1
NULL
6
2
6
7
7
2
3
10
I tried with ROWNUM, inner query, etc. but nothing worked out.
Can someone please point me in the right direction?

You need to use a cumulative sum of Count by RID and then select all rows where the cumulative count is less than or equal to 10.
Try this:
select
*
from
(
select
ID,
RID,
COUNT,
sum(COUNT) over (partition by RID order by ID) as cum_count
from
my_table
)
where
cum_count <= 10

Related

Row Number with specific window size

I want to group records by row numbers.
Like from row 1-3 in group 1 , 4-6 in group 2 , 7-9 in group 3 and so on.
Suppose below is the table structure:
Row NumberDataValue
1 A 10
2 A 5
3 A 1
4 A 33
5 A 2
6 A 127
1 B 1
2 B 0
3 B 7
4 B 7
5 B 5
6 B 8
7 B 1
8 B 0
I want a output like this:
GroupValue
1 10
1 5
1 1
2 33
2 2
2 127
1 1
1 0
1 7
2 7
2 5
2 8
3 1
3 0
I am using Oracle 11G.
I can achieve this using PL/SQL. But I have to use SQL only. As I have to use this query in a reporting tool.
If this is a duplicate question please provide the link of the answered question.
Subtract 1 from the column "RowNumber" and divide by 3.
Then use TRUNC() to get the integer part:
SELECT TRUNC(("RowNumber" - 1) / 3) + 1 "Group",
"Value"
FROM tablename
See the demo.
I would assume the name of the first column is ordering.
You can do:
select
1 + trunc(row_number() over(partition by data order by ordering) - 1) / 3,
value
from t
What you show looks like the output from something like this:
select ceil(rn/3) as grp, value
from your_table
order by rn;
Note that "row number" and "group" are reserved words/phrases which should not be used as column names. I used rn and grp instead.
I think the ceiling function is the simplest way to arrive at what you want. If you want to base it on the RowNumber column:
select ceil( RowNumber / 3.0) as grouping
If you want to calculate it yourself using row_number():
select ceil( row_number() over (order by RowNumber) / 3.0 ) as grouping

Assign Unique Group Id To Sets of Rows with Same Column Value Separated by Other value

I have some data that looks like this:
uid radius
1 10
2 10
3 10
4 2
5 4
6 10
7 10
8 10
What I want is for each group which has the same radius value to have its own unique id, for example:
uid radius GroupdId
1 10 1
2 10 1
3 10 1
4 2 2
5 4 3
6 10 4
7 10 4
8 10 4
What I don't want is the second group with radius 10 to have the same groupid as the first group (not 1).
I'm working on SQL Server but the solution should be the same across all databases.
(I've done this before, but for the life of me, I can't remember how I did it.)
Try this:
with t as
(
select
uid,
radius,
lag(radius,1) over (order by uid) as prev_rad
from
radtable
)
select
uid,
radius,
sum
(
case when radius = coalesce(prev_rad,radius) then 0 else 1 end
)
over
(
order by uid
) + 1 as GroupID
from
t

How to Subtotal Value with MAX

1.I have data as follows (just a subset - there are 20K records)
sku,id
1 1
1 2
1 2
1 2
1 3
1 4
1 1
1 2
1 3
1 4
1 4
1 4
1 5
1 6
1 6
2 1
2 1
2 2
2 3
2 3
2 3
2 4
2 4
2 5
2 5
2 6
2 7
2 1
2 2
2 3
The above values translate to
1 = 4 records
1 = 6 records
2 = 7 records
2 = 3 records
The MAX would just give me 6 for one and 7 for 2
The actual total is 1 = 10 and 2 = 10
How do I sum up to get the correct values?
You can use order by and some way of limiting rows. In standard SQL this would be:
select t.*
from t
order by id desc
fetch first 2 rows only;
However, some databases might use limit or select top or some other method.
No handling of ties here. Thousands of other questions handle this topic.
select sku, id
from (
select *, row_number() over (order by id desc) rn
from T
) t
where rn <= 2
order by rn desc;

SQL how to create a count that moves to the next number after a certain number of rows and then loops back to start over

I need to be able to create a column that has a count up to 3 but will provide numbers 1-3 three times each before starting over again.
My current code below only counts up to 3 and starts over. I need it to count each number 3 times then start over
Select personid, taskid, 1 + ( (row_number() over (order by personid) - 1) % 3) AS taskNumber2 from taskTable
Table in DB:
Personid taskid
1 1
1 2
2 3
2 4
2 5
3 6
4 7
4 8
5 9
5 10
5 11
Expected Results:
Personid taskid numberCount
1 1 1
1 2 1
2 3 1
2 4 2
2 5 2
3 6 2
4 7 3
4 8 3
5 9 3
5 10 1
5 11 1
You can use row_number to determine your value. Let the row number be x. Since you are repeating ervery 9th entry, take modulo 9. For easier calculating, subtract 1 before this. So now 0-2 -> 1, 3-5 -> 2, 6-8 -> 3. Thus devide by 3 (integer division) and add 1.
SELECT personid, taskid,
((row_number() OVER (ORDER BY personid) - 1) % 9) / 3 + 1 AS taskNumber2
FROM taskTable
ORDER BY personid
Also note, that I added the same ORDER BY clause to the whole statement as in the window function, thus assuring correct ordering (at least if this ordering is not ambigious, e.g. it is unique, perhaps a primary key)

SQL: how to use row_number() function to assign the same number for rows with duplicate ids in a repeating format

I have a table with two columns personid and taskid and want to use the ROW_NUMBER function to add a row that counts up to 3 but will duplicate the number as it counts if there are multiple rows for a personid.
The code below is only ordering by personid and repeating after the number 3, but I need it to order by personid and only go to the next number after all the taskid's for the personid are assigned to one number, or essentially any duplicate personid's I want to make sure they all only get one number assigned to it.
Select
personid,
taskid,
1 + ( (row_number() over (order by personid) - 1) % 3) as numberCount
from taskTable
Current Table Being Queried From:
PersonId Taskid
1 1
1 2
1 6
2 3
3 8
3 10
4 9
4 4
4 5
5 7
5 11
5 12
Expected Results After Query:
PersonId Taskid numberCount
1 1 1
1 2 1
1 6 1
2 3 2
3 8 3
3 10 3
4 9 1
4 4 1
4 5 1
5 7 2
5 11 2
5 12 2
Try this below script using DENSE_RANK -
SELECT *,
(DENSE_RANK() OVER(ORDER BY PersonId)-1)%3 + 1 AS numberCount
FROM your_table
I think you want dense_rank() and modulo arithmetic:
select t.*,
(dense_rank() over (order by personId) - 1) % 3) + 1 as numberCount
from t;
Note: The syntax for modulo arithmetic may vary in your database. Typically it is one of mod(), the % operator, or using mod as an operator.