Number of Rows Between Polarity Changes SQL - sql

I want to count the number of rows between polarity changes grouped by id in SQL. I'm thinking that there may be a clever way to use window functions to get the job done but I don't know what it is.
Consider data like this:
id
polarity
date
1
0
12/1
1
1
12/2
1
0
12/3
1
0
12/4
1
1
12/5
2
0
12/1
2
0
12/2
2
0
12/3
2
1
12/4
2
0
12/5
2
0
12/6
2
0
12/7
2
1
12/8
Is there a way to count the number of rows between each change in polarity to get something like this :
id
n
1
1
1
2
2
3
2
3

You can do:
select id, count(*) as n
from (
select *,
sum(i) over(partition by id order by date) as g
from (
select *, case when polarity <> lag(polarity)
over(partition by id order by date)
then 1 else 0 end as i
from t
) x
) y
group by id, g
having max(polarity) = 0

Related

How to reset running counts and start from 1 based on the condition and make previous row values as 0 in SQL?

For example there is some table with below data:
No Id Value
1 100 1
2 100 0
3 100 1
4 100 2
1 101 1
2 101 2
1 102 0
2 102 1
I have to write SQL query, which will return row count based on specific condition. If the value matches 0 then need to reset running counts and start from 1 and make previous row values as 0
So the result will be like:
No Id Value Running Count
1 100 1 0
2 100 0 0
3 100 1 1
4 100 1 2
1 101 1 1
2 101 2 2
1 102 1 0
2 102 0 0
Your sample dataset is quite limited so I'm not sure of all edge cases but see if the following works for you. If not it might help get you there.
This gets a running count using a window & case expression and uses lead to check the next value.
If the current value or next value is 0 the count is 0, otherwise it's the running count subtracting 1 if there is a 0 in the Id block indicating the count was reset.
select No, Id, Value,
case when value = 0 or nv = 0
then 0
else
rc - case when Min(value) over(partition by id) = 0 then 1 else 0 end
end Running_Count
from (
select *,
Sum(case when value = 0 then 0 else 1 end) over(partition by id order by no) rc,
Lead(Value) over(partition by Id order by No)nv
from t
)t;

Creating duplicating rank over multiple columns

I have data as below where for one customer ID there are several orders (KEY) which is the primary key. I have also have a activity flag as below (either 0 or 1).
CUST_ID KEY FLAG
1 1 1
1 2 1
1 3 1
1 4 0
1 5 0
1 6 1
1 7 1
1 8 0
1 9 0
Now I want to create ranks as below based on the FLAG. The idea is to give same Rank as preceding row if the FLAG is same as preceding row. The Rank increments if the current value is different from preceding value.
CUST_ID KEY FLAG RN
1 1 1 1
1 2 1 1
1 3 1 1
1 4 0 2
1 5 0 2
1 6 1 3
1 7 1 3
1 8 0 4
1 9 0 4
I'm new to SQL, so please let me know if I need to reframe my question.
Use LAG() window function to get each row's previous flag and then use SUM() window function to create the rankings:
SELECT CUST_ID, KEY, FLAG,
SUM(CASE WHEN FLAG <> prev_FLAG THEN 1 END) OVER (PARTITION BY CUST_ID ORDER BY KEY) RN
FROM (
SELECT *, LAG(FLAG, 1, FLAG - 1) OVER (PARTITION BY CUST_ID ORDER BY KEY) prev_FLAG
FROM tablename
) t;
See the demo.
The code could be simplified, depending on the specific database that you use.

How to select a Algokey when [ UserSelect] column has any of row value is 1 otherwise switch to[ SytemSelect]column haivng row value is 1

I have a table with Scenario,Product,AlgoKey,User Select,System Select columns, I have to select the algo key for each scenario, The first priority goes to user selected otherwise system selected.
I have Shared my Inout & output result below, could you please help me how to write query for this.
Scenario
Product
AlgoKey
User Select
SystemSelect
1
P101
1
0
1
1
P102
2
1
0
2
P101
1
0
1
2
P102
2
0
0
3
P101
1
1
1
3
P102
2
0
0
4
P101
1
0
0
4
P102
2
0
1
OutPut :
Scenario
AlgoKey
Columnselected
1
2
User
2
1
System
3
1
User
4
2
System
here is how you can do it
select scenario , AlgoKey, case when Userselect = 1 then 'User' else 'System' end Columnselected
from (
select *, ROW_NUMBER() over (partition by scenario,productkey order by userselect desc, systemselect desc) rn
from tableName
) t
where rn = 1

Order a column by pair of values

I have 2 simple columns:
one column is simply an ID column and the other column is some sort of boolean type column.
ID V
0 1
1 0
2 0
3 1
4 1
5 0
I want to order the rows by pair of values (0,1) of column V
(while still keeping the ID as minimal as possible):
ID V
1 0
0 1
2 0
3 1
5 0
4 1
How do I do that ?
Seems you want get rows for 0 and 1 in turn:
select id, v
from tab
order by
row_number()
over (partition by v
order by id)
,v

Count occurrences of field values as they are displayed in order

thanks in advance for the help and sorry for how the "table" looks. Here's my question...
Let's say I have a subquery with this table (imagine the bold as column headers) as its output -
id 1 1 2 3 3 3 3 4 5 6 6 6
action o c o c c o c o o c c c
I would like my new query to output -
id 1 1 2 3 3 3 3 4 5 6 6 6
action o c o c c o c o o c c c
ct 1 2 1 1 2 3 4 1 1 1 2 3
#c 0 1 0 1 2 2 3 0 0 1 2 3
#o 1 1 1 0 0 1 1 1 1 0 0 0
where ct stands for count. Basically, I want to count (for each id) the occurrences of consecutive id and action as they happen. Let me know if this makes sense, and if not, how I can clarify my question.
Note: I realize the lag/lead functions may be helpful in this situation, along with the row_number() function. Looking for as many creative solutions as possible!
You are looking for the row_number() analytic function:
select id, action, row_number() over (partition by id order by id) as ct
from table t;
For #c and #o, you want cumulative sum:
select id, action, row_number() over (partition by id order by id) as ct,
sum(case when action = 'c' then 1 else 0 end) over
(partition by id order by <some column here>) as "#c",
sum(case when action = 'c' then 1 else 0 end) over
(partition by id order by <some column here>) as "#o"
from table t;
The one caveat is that you need a way to specify the order of the rows -- an id or date time stamp or something. SQL result sets and tables are inherently unordered, so there is no idea that one row comes before or after another.
SQL> select id, action,
2 row_number() over(partition by id order by rowid) ct,
3 sum(decode(action,'c',1,0)) over(partition by id order by rowid) c#,
4 sum(decode(action,'o',1,0)) over(partition by id order by rowid) o#
5 from t1
6 /
ID A CT C# O#
---------- - ---------- ---------- ----------
1 o 1 0 1
1 c 2 1 1
2 o 1 0 1
3 c 1 1 0
3 c 2 2 0
3 o 3 2 1
3 c 4 3 1
4 o 1 0 1
5 o 1 0 1
6 c 1 1 0
6 c 2 2 0
6 c 3 3 0
P.S. Sorry Gordon, didn't see your post.