i have a table like this:
Number Price Type Date Time
------ ----- ---- ---------- ---------
23456 0,665 SV 2014/02/
Your question (and Anon's excellent answer) is part of the SQL of islands and gaps. In this answer, I will try to examine the "row_number() magic" in detail.
I've made a simple example based on events in a ballgame. For each event, we'd like to print the previous and next quarter related message:
create table TestTable (id int identity, event varchar(64));
insert TestTable values
('Start of Q1'),
('Free kick'),
('Goal'),
('End of Q1'),
('Start of Q2'),
('Penalty'),
('Miss'),
('Yellow card'),
('End of Q2');
Here's a query showing off the "row_number() magic" approach:
; with grouped as
(
select *
, row_number() over (order by id) as rn1
, row_number() over (
partition by case when event like '%of Q[1-4]' then 1 end
order by id) as rn2
from TestTable
)
, order_in_group as
(
select *
, rn1-rn2 as group_nr
, row_number() over (partition by rn1-rn2 order by id) as rank_asc
, row_number() over (partition by rn1-rn2 order by id desc)
as rank_desc
from grouped
)
select *
, lag(event, rank_asc) over (order by id) as last_event_of_prev_group
, lead(event, rank_desc) over (order by id) as first_event_of_next_group
from order_in_group
order by
id
row_number()
s. The first is 1 2 3
for each row in the table. The second row_number()
places pause announcements in one list, and other events in a second list. The difference between the two, rn1 - rn2
, is unique for each section of the game. It's helpful to check difference in the example output: it's in the group_nr
column. You'll see that each value corresponds to one section of the game.1 2 3
for the ascending order, and 3 2 1
for the descending order.lag()
and lead()
how far to jump. We have to lag rank_asc
rows to find the final row of the previous section. To find the first row of the next section, we have to lead rank_desc
rows.Hope this helps clarifying the "magic" of Gaps and Islands. Here is a working example at SQL Fiddle.