Oracle SQL - Running Sum based on group by and condition - sql

I have table that looks like
ID SEQ LABEL COUNT
1 1 0 3
1 2 0 2
1 3 0 6
1 4 1 2
1 5 0 3
1 6 0 5
2 1 0 2
2 2 1 1
2 3 0 3
I would like to create a column called running_count. It calculates cumulative sum of the column count till the Label is 1 and then reset and start cumulative sum again.
Expected Output:
ID SEQ LABEL1 COUNT1 RUNNING_COUNT
1 1 0 3 3
1 2 0 2 5
1 3 0 6 14
1 4 1 2 16
1 5 0 3 3
1 6 0 5 8
2 1 0 2 2
2 2 1 1 3
2 3 0 3 3
I tried the following query
SELECT A.*, SUM(COUNT1) over (partition by ID,LABEL1 order by SEQ) as RUNNING_COUNT FROM TABLE_1 A
The problem here is that the cumulative sum stops in previous row(Seq) for Label = 1. I need to get the running sum till Label = 1 for Each ID based on Seq.
The Wrong Output I am getting
ID SEQ LABEL1 COUNT1 RUNNING_COUNT
1 1 0 3 3
1 2 0 2 5
1 3 0 6 14
1 4 1 2 2
1 5 0 3 3
1 6 0 5 8
2 1 0 2 2
2 2 1 1 1
2 3 0 3 3

You could make a first window sum() to define the groups, then use it as partition for the outer query:
select
t.*,
sum(count1) over(partition by id, grp order by seq) running_count
from (
select
t.*,
sum(label) over(partition by id order by seq desc) grp
from mytable t
) t
Demo on DB Fiddle:
ID | SEQ | LABEL | COUNT1 | GRP | RUNNING_COUNT
-: | --: | ----: | -----: | --: | ------------:
1 | 1 | 0 | 3 | 1 | 3
1 | 2 | 0 | 2 | 1 | 5
1 | 3 | 0 | 6 | 1 | 11
1 | 4 | 1 | 2 | 1 | 13
1 | 5 | 0 | 3 | 0 | 3
1 | 6 | 0 | 5 | 0 | 8
2 | 1 | 0 | 2 | 1 | 2
2 | 2 | 1 | 1 | 1 | 3
2 | 3 | 0 | 3 | 0 | 3

Related

Update column according max value from other column SQL [duplicate]

This question already has an answer here:
SQL Set column with Key and max value from other colum
(1 answer)
Closed 1 year ago.
Taking the max value of column 'time', I need update the column 'register' group by Identification column, set register = 1 and the rest register = 0
Initial table:
Identification | time | register
1 | 0 | 0
1 | 7 | 0
1 | 3 | 0
2 | 10 | 0
2 | 5 | 0
2 | 0 | 0
3 | 6 | 0
3 | 5 | 0
3 | 0 | 0
Ending table:
Identification | time | register
1 | 0 | 0
1 | 7 | 1
1 | 3 | 0
2 | 10 | 1
2 | 5 | 0
2 | 0 | 0
3 | 6 | 1
3 | 5 | 0
3 | 0 | 0
In SQL 2017, the table contains thousand of registers
Seems like you want a CASE expression and a windowed MAX:
SELECT Identification,
[time],
CASE [time] WHEN MAX([time]) OVER (PARTITION BY Identification) THEN 1 ELSE 0 END AS register
FROM dbo.YourTable;

Sql Query that returns columns with counts based on grouped values from one table

I have a table of Tasks. There may be many tasks with various statuses to one Activity. I need to add columns to the main Activity view that displays the count of how many open tasks, closed tasks and total tasks. I thought I would create a view with the totals grouped per Activity then join via the ActivityID. I am having trouble creating the view with the correct figures, please help.This doesn't return the correct numbers:
The status values that equate to an 'OpenTasks' is 0,1 & 3. 'ClosedTasks' is 3
Existing table - Tasks
ID | WorkID| Status
1 | 5 | 2
2 | 5 | 2
3 | 5 | 0
4 | 5 | 3
5 | 6 | 2
6 | 7 | 0
7 | 7 | 0
8 | 9 | 1
9 | 9 | 2
The resulting view I require is:
WorkID | OpenTasks | ClosedTasks | TotalTasks
5 | 2 | 2 | 4
6 | 0 | 1 | 1
7 | 2 | 0 | 2
9 | 1 | 1 | 2
SELECT top 10000 WorkActivityId,
COUNT(CASE WHEN status = 2 then 1 ELSE NULL END) as "ClosedTasks",
COUNT(CASE WHEN status <> 2 then 1 ELSE NULL END) as "OpenTasks",
COUNT(CASE WHEN status < 10 then 1 ELSE NULL END) as "TotalTasks"
FROM [SDMTWorkActivity].[WorkActivity].[Tasks]
GROUP BY WorkActivityId order by WorkActivityId
I am not great as SQL so appreciate any advice Thank you
Your query should be working but you can try the following using sum
SELECT
WorkId,
SUM(CASE WHEN status <> 2 then 1 ELSE 0 END) as "OpenTasks",
SUM(CASE WHEN status = 2 then 1 ELSE 0 END) as "ClosedTasks",
SUM(CASE WHEN status < 10 then 1 ELSE 0 END) as "TotalTasks"
FROM [SDMTWorkActivity].[WorkActivity].[Tasks]
GROUP BY WorkId
order by WorkId
output:
| WorkId | OpenTasks | ClosedTasks | TotalTasks |
| ------ | --------- | ----------- | ---------- |
| 5 | 2 | 2 | 4 |
| 6 | 0 | 1 | 1 |
| 7 | 2 | 0 | 2 |
| 9 | 1 | 1 | 2 |

SQL : Get the 3 first occurrences of a field

I have a PostgreSQL table with 2 fields like the following. Field A is the primary key.
A | B
------
1 | 1
2 | 1
3 | 1
4 | 1
5 | 2
6 | 2
7 | 2
8 | 2
9 | 2
10 | 3
11 | 3
I'm looking for a request to get only the 3 first occurrences of B, like this:
A | B
1 | 1
2 | 1
3 | 1
5 | 2
6 | 2
7 | 2
10 | 3
11 | 3
Does somebody have a solution?
You want row_number() :
select t.*
from (select t.*, row_number() over (partition by b order by a) as seq
from table t
) t
where seq <= 3;

Counting Using Duplicate Column

I have a table below.
ClientID | FileCount | LinkNumber | ActualFileCount |
----------|-----------|------------|-----------------|
1 | 1 | 0 | 1 |
----------|-----------|------------|-----------------|
2 | 1 | 0 | 1 |
----------|-----------|------------|-----------------|
3 | 2 | 0 | 2 |
----------|-----------|------------|-----------------|
4 | 1 | 123 | 1 |
----------|-----------|------------|-----------------|
5 | 1 | 123 | 0 |
----------|-----------|------------|-----------------|
6 | 2 | 456 | 2 |
----------|-----------|------------|-----------------|
7 | 2 | 456 | 0 |
----------|-----------|------------|-----------------|
8 | 2 | 456 | 0 |
----------|-----------|------------|-----------------|
9 | 1 | 789 | 1 |
----------|-----------|------------|-----------------|
10 | 1 | 789 | 0 |
Basically if the LinkNumber is 0 then copy the FileCount column into ActualFileCount column. However, if the LinkNumber is not 0 then the ActualFileCount must be only a single value related to that LinkNumber.
For example ClientID 4 and 5, they are husband and wife, so we link them both. The system give them each FileCount 1. However, since they are link, there is only 1 ActualFileCount for both (only 1 'physical' file for both).
I use the syntax below I excel (using an example for ClientID 3 and ClientId 4)
If (LinkNumber = 0 then FileCount else
(If (LinkNumber for ClientID 4 = LinkNumber for ClientID 3 then 0 else FileCount)
When I translate it to SQL Server 2012, it doesn't work.
select ClientID, file_count, LinkNumber,
If LinkNumber = 0 then file_count
else If LinkNumber + 1 = LinkNumber Then 0 else FileCount
end
as ActualFileCount
from TableA
order by LinkNumber asc
Thanks guys for your help.
SELECT clientid,
filecount,
linknumber,
CASE WHEN linknumber = 0 OR rnum = 1
THEN filecount
ELSE 0
END actualfilecount
FROM (SELECT *,
ROW_NUMBER() OVER (PARTITION BY linknumber ORDER BY clientid) rnum
FROM t_client
) t
Result
clientid filecount linknumber actualfilecount
1 1 0 1
2 1 0 1
3 2 0 2
4 1 123 1
5 1 123 0
6 2 456 2
7 2 456 0
8 2 456 0
9 1 789 1
10 1 789 0
WITH result of ROW_NUMBER()
clientid filecount linknumber actualfilecount rnum
1 1 0 1 1
2 1 0 1 2
3 2 0 2 3
4 1 123 1 1
5 1 123 0 2
6 2 456 2 1
7 2 456 0 2
8 2 456 0 3
9 1 789 1 1
10 1 789 0 2

Delete rows with repeat column values

I have a table that looks like this:
ID VAR1 VAR2 VAR3 VAR4 VAR5 VAR6 VAR7 VAR8 VAR9 VAR10
1 2 1 3 5 2 1 3 5 3 1
2 1 1 1 1 1 1 1 1 1 1
3 1 3 4 7 2 4 1 3 4 6
4 2 2 2 2 2 2 2 2 2 2
5 1 3 5 6 7 4 6 7 4 6
6 3 3 3 3 3 3 3 3 3 3
How do I delete rows (in this case ID # 2,4,6) which have non-distinct values, i.e. the same number in every column, (1,1,1,1,1)?
How about...
DELETE FROM tablename WHERE
VAR1=VAR2
AND VAR2=VAR3
AND VAR3=VAR4
AND VAR4=VAR5
AND VAR5=VAR6
AND VAR6=VAR7
AND VAR7=VAR8
AND VAR8=VAR9
AND VAR9=VAR10
Hopefully you'll need to run this only once - I imagine most of the vars will not be indexed so you'll might end up locking the table or this delete. It would be better to prevent these rows from being inserted I guess.
in SQL Server; using cross apply(values ...) to unpivot the columns along then aggregate and filter with count(distinct ...)=1:
delete t
where id in (
select t.id
from t
cross apply (values (VAR1),(VAR2),(VAR3),(VAR4),(VAR5),(VAR6),(VAR7),(VAR8),(VAR9),(VAR10)
) u(Var)
group by t.id
having count(distinct u.var)=1
)
rextester demo: http://rextester.com/WZE91559
returns:
+----+------+------+------+------+------+------+------+------+------+-------+
| ID | VAR1 | VAR2 | VAR3 | VAR4 | VAR5 | VAR6 | VAR7 | VAR8 | VAR9 | VAR10 |
+----+------+------+------+------+------+------+------+------+------+-------+
| 1 | 2 | 1 | 3 | 5 | 2 | 1 | 3 | 5 | 3 | 1 |
| 3 | 1 | 3 | 4 | 7 | 2 | 4 | 1 | 3 | 4 | 6 |
| 5 | 1 | 3 | 5 | 6 | 7 | 4 | 6 | 7 | 4 | 6 |
+----+------+------+------+------+------+------+------+------+------+-------+