Order by with repeat sequence sql server - sql

I have a table that looks somewhat like this:
Points Sequence
---------- --------
100,001.00 0
100,002.00 0
100,003.00 0
100,004.00 0
100,005.00 1
100,006.00 1
100,007.00 1
100,008.00 1
100,009.00 2
100,010.00 2
100,011.00 2
100,012.00 2
Is there any way we can achieve following output using order by.
Points Sequence
---------- --------
100,001.00 0
100,005.00 1
100,009.00 2
100,002.00 0
100,006.00 1
100,010.00 2
100,003.00 0
100,008.00 1
100,011.00 2
100,004.00 0
100,007.00 1
100,012.00 2
Thanks in advance for help.

If I understand correctly, you want to interleave the rows, so rows with the same sequence are separated rather than being adjacent in the result set.
You can use row_number() in an order by clause:
select t.*
from t
order by row_number() over (partition by sequence order by points),
sequence;

Related

How to Number a sequence block

Given the Sequence of numbers below, how can I assign a Sequence number so that each block which starts with a 1 and ends with a 0 is given a unique identifying number? How can I create the Sequence Number column using TSQL?
Sequence
SequenceNumber
1
1
1
1
0
1
1
2
1
2
1
2
0
2
1
3
0
3
Use COUNT OVER to count zeros. You need some column to determine the order. I am calling it sortkey in the following query:
select
t.*,
count(case when sequence = 0 then 1 end)
over (order by sortkey
rows between unbounded preceding and 1 preceding) + 1
as sequence_number
from mytable t
order by sortkey;
Demo: https://dbfiddle.uk/3DZBeDMQ

how can i alternate between 0 and 1 values in sql server?

I want to create a select which will alternate between 1 and 0
my table looks like that
id1 id2 al
11 1 1
40 1 0
12 1 0
237 1 1
but I want to make it like that
id1 id2 al
40 1 0
11 1 1
12 1 0
237 1 1
I want to keep the same values in my table but I just want to switch the rows to alternate between 0 and 1
Consider:
select *
from mytable
order by row_number() over(partition by al order by id1), al
This alternates 0 and 1 values - if the groups have a different number of rows, then, once the smallest group exhausts, all remaining rows in the other group appear at the end of the resultset.
I am unsure which column you want to use to order the rows within each group - I assumed id1, but you might want to change that to your actual requirement.

Is there a way to group this data?

Data Looks like -
1
2
3
1
2
2
2
3
1
5
4
1
2
So whenever there is a 1, it marks the beginning of a group which includes all the elements until it hits the next 1. So here,
1 2 3 - group 1
1 2 2 2 3 - group 2
and so on..
What would be the SQL query to show the average for every such group.
I could not figure out how to group them without using for loops or PLSQL code.
Result should look like two columns, one with the actual data and col 2 with the average value-
1 - avg value of 1,2 3
2
3
1 - avg value of 1,2,2,2,3
2
2
2
3
1 - avg value of 1,5,4
5
4
1 - avg value of 1,2
2
SQL tables represent unordered sets. There is no ordering, unless a column specifies the ordering. Let me assume that you have such a column.
You can identify the groups using a cumulative sum:
select t.*,
sum(case when t.col = 1 then 1 else 0 end) over (order by ?) as grp
from t;
? is the column that specifies the ordering.
You can then calculate the average using aggregation:
select grp, avg(col)
from (select t.*,
sum(case when t.col = 1 then 1 else 0 end) over (order by ?) as grp
from t
) t
group by grp;

Calculate "position in run" in SQL

I have a table of consecutive ids (integers, 1 ... n), and values (integers), like this:
Input Table:
id value
-- -----
1 1
2 1
3 2
4 3
5 1
6 1
7 1
Going down the table i.e. in order of increasing id, I want to count how many times in a row the same value has been seen consecutively, i.e. the position in a run:
Output Table:
id value position in run
-- ----- ---------------
1 1 1
2 1 2
3 2 1
4 3 1
5 1 1
6 1 2
7 1 3
Any ideas? I've searched for a combination of windowing functions including lead and lag, but can't come up with it. Note that the same value can appear in the value column as part of different runs, so partitioning by value may not help solve this. I'm on Hive 1.2.
One way is to use a difference of row numbers approach to classify consecutive same values into one group. Then a row number function to get the desired positions in each group.
Query to assign groups (Running this will help you understand how the groups are assigned.)
select t.*
,row_number() over(order by id) - row_number() over(partition by value order by id) as rnum_diff
from tbl t
Final Query using row_number to get positions in each group assigned with the above query.
select id,value,row_number() over(partition by value,rnum_diff order by id) as pos_in_grp
from (select t.*
,row_number() over(order by id) - row_number() over(partition by value order by id) as rnum_diff
from tbl t
) t

SQL Server GROUP BY COUNT Consecutive Rows Only

I have a table called DATA on Microsoft SQL Server 2008 R2 with three non-nullable integer fields: ID, Sequence, and Value. Sequence values with the same ID will be consecutive, but can start with any value. I need a query that will return a count of consecutive rows with the same ID and Value.
For example, let's say I have the following data:
ID Sequence Value
-- -------- -----
1 1 1
5 1 100
5 2 200
5 3 200
5 4 100
10 10 10
I want the following result:
ID Start Value Count
-- ----- ----- -----
1 1 1 1
5 1 100 1
5 2 200 2
5 4 100 1
10 10 10 1
I tried
SELECT ID, MIN([Sequence]) AS Start, Value, COUNT(*) AS [Count]
FROM DATA
GROUP BY ID, Value
ORDER BY ID, Start
but that gives
ID Start Value Count
-- ----- ----- -----
1 1 1 1
5 1 100 2
5 2 200 2
10 10 10 1
which groups all rows with the same values, not just consecutive rows.
Any ideas? From what I've seen, I believe I have to left join the table with itself on consecutive rows using ROW_NUMBER(), but I am not sure exactly how to get counts from that.
Thanks in advance.
You can use Sequence - ROW_NUMBER() OVER (ORDER BY ID, Val, Sequence) AS g to create a group:
SELECT
ID,
MIN(Sequence) AS Sequence,
Val,
COUNT(*) AS cnt
FROM
(
SELECT
ID,
Sequence,
Sequence - ROW_NUMBER() OVER (ORDER BY ID, Val, Sequence) AS g,
Val
FROM
yourtable
) AS s
GROUP BY
ID, Val, g
Please see a fiddle here.