is possible to see a previous row after a selected one? - sql

i have created a table like this
create table numbers(
first int ...
second int...
third int ...
fourth ....
fifth int..
sixt int ...
id primary key..
...);
every sextain has an id for identification.
i would like to see a previuous row of the one i selected
example
select * from numbers where first=6 And second=54;
as output (we will have all the numbers were first and second are 6 and 54 with id)
first second 3 4 5 6 id
6 54 10 11 13 66 10
6 54 7 8 9 10 520
i would like too see row 9 and row 519 is there a way to see those? i know i
could do
select * from numbers where id=9;
select * from nbumbers where id= 519;
but i have 50-60 row it's impossible to do
individually one by one.

you can use
SELECT * FROM NUMBERS WHERE ID IN
(SELECT ID -1 FROM NUMBERS WHERE first = 6 and second = 54);

You can use lead():
select n.*
from (select n.*,
lead(first) over (order by id) as next_first,
lead(second) over (order by id) as next_second
from numbers n
) n
where next_first = 6 and next_second = 54;
Another method would use a cumulative sum:
select n.*
from (select n.*,
max(case when first = 6 and second = 54 then id end) over
(order by id
rows between unbounded preceding and 1 preceding
) as prev_id
from numbers n
) n
where prev_id = id;

You probably want:
select
n.*
from (
select * from numbers where first = 6 and second = 54
) x
join numbers n on n.id = x.id - 1

Related

Get Max Rate from users table and get the next 2 rows and previous 2 rows

If I have a users table contains a column called Rate and I need to get the maximum value from the rate column and name it position (position will be 1 for the max value only) after that I need to get a specific row by Id . and select the next 2 rows (next means the row's rate is bigger than the row I got) and previous 2 rows (rows' rate is smaller.
what is the query that can give me this result??
Ex:
Id
rate
1
80
2
50
3
100
4
90
5
10
6
20
and I need to get row has Id 2,the result should be:
Id
rate
4
90
1
80
2
50<------------------>
6
20
5
10
One option is literally just how it's written, unioned together:
select * from
(
select top 2 *
from x
where
rate <= (select rate from x where id = 2)
and id <> 2
order by rate desc
) lower
union all
select *
from x
where id = 2
union all
select * from
(
select top 2 *
from x
where
rate >= (select rate from x where id = 2)
and id <> 2
order by rate
) higher
A slightly more efficient version of #CauisJard's answer
Get the rate of the row id = 2 first
Then cross apply everything else
Combine the unioned queries so id = 2 is retrieved with two others.
select
data.*
from (
select rate
from x
where id = 2
) StartPoint
cross apply
(
select *
from (
select top (3) *
from x
where rate <= StartPoint.rate
order by rate desc
) lower
union all
select *
from (
select top (2) *
from x
where rate >= StartPoint.rate
and id <> 2
order by rate
) higher
) data;

How to update a column for all rows by increment of 10

I have a situation where there are column (int) named 'position' in table. I need to update that column by increment of 10 for every row.
I can create a function for that, but can it be achieved by simple query?
Quick example of current values and desired ones:
| ID | POSITION | .... | WHAT I WANT POSITION TO BE |
1 10 xxx 10
2 21 xxx 20
3 22 xxx 30
5 30 xxx 40
.... etc
You can use row_number() and arithmetic:
select t.*,
10 * row_number() over (order by position) as new_position
from t;
If you want to update the value, then you can include this in an update:
update t
set position = tt.new_position
from (select t.*,
10 * row_number() over (order by position) as new_position
from t
) tt
where tt.id = t.id;

Delete rows, which are duplicated and follow each other consequently

It's hard to formulate, so i'll just show an example and you are welcome to edit my question and title.
Suppose, i have a table
flag id value datetime
0 b 1 343 13
1 a 1 23 12
2 b 1 21 11
3 b 1 32 10
4 c 2 43 11
5 d 2 43 10
6 d 2 32 9
7 c 2 1 8
For each id i want to squeze the table by flag columns such that all duplicate flag values that follow each other collapse to one row with sum aggregation. Desired result:
flag id value
0 b 1 343
1 a 1 23
2 b 1 53
3 c 2 75
4 d 2 32
5 c 2 1
P.S: I found functions like CONDITIONAL_CHANGE_EVENT, which seem to be able to do that, but the examples of them in docs dont work for me
Use the differnece of row number approach to assign groups based on consecutive row flags being the same. Thereafter use a running sum.
select distinct id,flag,sum(value) over(partition by id,grp) as finalvalue
from (
select t.*,row_number() over(partition by id order by datetime)-row_number() over(partition by id,flag order by datetime) as grp
from tbl t
) t
Here's an approach which uses CONDITIONAL_CHANGE_EVENT:
select
flag,
id,
sum(value) value
from (
select
conditional_change_event(flag) over (order by datetime desc) part,
flag,
id,
value
from so
) t
group by part, flag, id
order by part;
The result is different from your desired result stated in the question because of order by datetime. Adding a separate column for the row number and sorting on that gives the correct result.

How to select top 10% of values in SQL

I know it's possible to select the maximum value in SQL with MAX(), but if I have a table with two columns, an ID and a value, is it possible to select the top 10% of values for each ID. There is not a set number of values for each ID.
EDIT: Apologies for not being clearer,
I'm working with Microsoft SQL server Managment studio. Table A looks like:
ID, Value
112345, 1
112345, 2
112345, 3
112345, 2
112345, 3
112345, 18
112345, 32
112357, 10
112346, 15
112346, 16
If it were to select the top 50% for each I would want the select to produce:
ID, Value
112345, 3
112345, 3
112345, 18
112345, 32
112357, 10
112346, 16
I would prefer if the number of returned rows was rounded up, eg. 10% of an ID that had 4 rows would still return 1 value
Assuming you want the first 10% of rows ordered by Value (desc), you can achieve that by using window functions:
select * from (
select ID, Value, COUNT(*) over (partition by ID) as countrows, ROW_NUMBER() over (partition by ID order by Value desc) as rowno from mytable) as innertab
where rowno <= floor(countrows*0.1+0.9)
order by ID, rowno
The floor-thing brings 1 row per 1-10 rows, 2 rows for 11-20 rows and so on.
Alternatively you could use CROSS APPLY and specify TOP n PERCENT
SELECT x.*
FROM ( SELECT DISTINCT ID FROM tab ) a
CROSS APPLY ( SELECT TOP 10 PERCENT ID, Value FROM tab b WHERE b.ID = a.ID) x
TOP n PERCENT will produce at least one row.

SQL - Select first n row where next n Row values are sequential + 1

I have a table with row ID and Cct numbers. The Cct column can be +1 sequential depending on the preceeding select statement.
I want to find the first row where the next n rows cct no. increments + 1 to n-1.
Sample
ID Cct
1 1
2 3
7 5
8 6
10 9
11 10
12 11
if n = 2 I want to select row with ID 7 because it is the first time that the next n rows cct value are value + 1
if n = 3 I want to select row with ID 10 as the next n-1 rows are incremented by + 1
Hope this is clear
I think I get it. You are looking for lengths of sequences in the data, where a sequence is incremented by 1.
You can identify them using row_number() and subtraction -- the difference is fixed for a sequence.
So:
select top 1 min(id), count(*) as length
from (select s.*, (cct - row_number() over (order by id)) as grp
from sample s
) s
group by grp
having count(*) >= #n
order by min(id)
This gets the first time that a sequence of length (at least) #n appears in the data.