how to find previous & forward relation of data in single query - sql-server

I have table :
ID Person_ID Person_Relative_ID
1 10 20
2 20 30
3 13 15
4 30 40
5 55 56
6 40 50
Here we can see the person & person_relative_id chain is going like 10 - 20 - 30 - 40 - 50
Now if user search Person_Relative_ID of person_id = 20 then result would be like: [All its relation]
Person_Relative_ID
10
30
40
50
Or user want to search Person_Relative_ID for person_id = 40 . then result like
Person_Relative_ID
10
20
30
50
Or user want to search Person_Relative_ID for person_id = 50 . then result like
Person_Relative_ID
10
20
30
40
Any suggestion really appreciated.

Well I'm not sure this is the most performance effective solution, and I'd have liked to deal with a single recursive CTE instead of two, but this works at least.
Just replace the references to the temporary table I used to test this, with your real table. But what it does, is it uses two recursive CTE's to find all references above (CTEUp) and below (CTEDown) your ID, and then shows them in order, except for your searched ID.
Note: This is for SQL Server, not Oracle.
-- Creating dummy variables for testing
DECLARE #PERSONS TABLE (ID INT IDENTITY(1,1), Person_ID INT, Person_Relative_ID INT)
INSERT INTO #PERSONS VALUES (10,20), (20,30), (13,15), (30,40), (55,56), (40,50)
-- Variable for searched ID, the actual script begins here
DECLARE #SEARCHED_ID INT
SET #SEARCHED_ID = 20
;WITH CTEUp AS
-- Fetching all relations above the ID
(SELECT Person_ID
FROM #PERSONS
WHERE Person_ID = #SEARCHED_ID
UNION ALL
SELECT Person_Relative_ID
FROM #PERSONS P
JOIN CTEUp C ON C.Person_ID = P.Person_ID
AND P.Person_Relative_ID > C.Person_ID)
, CTEDown AS
-- Fetching all relations below the ID
(SELECT Person_ID
FROM #PERSONS
WHERE Person_Relative_ID = #SEARCHED_ID
UNION ALL
SELECT P.Person_ID
FROM #PERSONS P
JOIN CTEDown C ON C.Person_ID = P.Person_Relative_ID
AND P.Person_ID < C.Person_ID)
-- Showing results
SELECT Person_ID
FROM
(SELECT *
FROM CTEDown
UNION ALL
SELECT *
FROM CTEUp) SRC
WHERE Person_ID <> #SEARCHED_ID --... minus the ID, as per your example
ORDER BY Person_ID ASC

Just gave a try in Oracle, could be better but still it works
with tab(ID, Person_ID, Person_Relative_ID) as (
SELECT 1, 10, 20 from dual union all
SELECT 2, 20, 30 from dual union all
SELECT 3, 13, 15 from dual union all
SELECT 4, 30, 40 from dual union all
SELECT 5, 55, 56 from dual union all
SELECT 6, 40, 50 from dual),
---------
--End of data preparation
---------
filter_tab as (
select 40 as id from dual), --> Put the search id here
final_tab(person_id) as (
select person_id
from tab
start with person_relative_id = (select id from filter_tab)
connect by prior person_id = person_relative_id
union
select person_relative_id
from tab
start with person_id = (select id from filter_tab)
connect by prior person_relative_id = person_id)
select *
from final_tab
where not exists (select 'x'
from filter_tab
where id = person_id )
order by 1;
Output:
PERSON_ID
---------
10
20
30
50
I just traversed to both ends from the start point, did union of the result and excluded the search id.

In SQL Server 2012 and above, you can use LAG and LEAD function.
Here is a sample:
SELECT TOP 1000 [n], LAG([n]) OVER(ORDER BY [n] ), LEAD([n]) OVER (ORDER BY [n])
FROM [dbo].[Nums]
it generates results:
n LAG LEAD
1 NULL 2
2 1 3
3 2 4
4 3 5
5 4 6

If you are using SQL2005 and above, SQL Recursive CTE structured SQL query can be used for querying hierarchical data models like in your case
Below query uses also multiple CTE queries to prevent usage of unnecessary temp tables or table variables
declare #id smallint = 50
;with cte as (
select Person_ID, Person_Relative_ID
from PersonRelative
where Person_ID = #id OR Person_Relative_ID = #id
union all
select P.Person_ID, P.Person_Relative_ID
from PersonRelative P
inner join CTE on CTE.Person_ID = P.Person_Relative_ID
), cte2 as (
select Person_ID from cte
union
select Person_Relative_ID from cte
), cte3 as (
select Person_ID, Person_Relative_ID
from PersonRelative
where Person_ID = #id OR Person_Relative_ID = #id
union all
select P.Person_ID, P.Person_Relative_ID
from PersonRelative P
inner join CTE3 on CTE3.Person_Relative_ID = P.Person_ID
), cte4 as (
select Person_ID from cte3
union
select Person_Relative_ID from cte3
)
select * from cte4 where Person_ID <> #id
union
select * from cte2 where Person_ID <> #id

Related

How to get previous record if current record does not exist in table

my table like this
Id Date type quantity
1 29/04/2019 APPLE 2
2 29/04/2019 Banana 15
3 29/04/2019 Mango 100
4 29/04/2019 Grapes 50
5 29/04/2019 Fish 80
6 30/04/2019 APPLE 4
7 30/04/2019 Grapes 100
8 30/04/2019 Fish 90
9 01/05/2019 APPLE 6
10 01/05/2019 Banana 30
11 01/05/2019 Grapes 150
12 01/05/2019 Fish 100
13 02/05/2019 Mango 200
14 02/05/2019 Grapes 200
15 02/05/2019 Fish 110
16 03/05/2019 APPLE 8
17 03/05/2019 Banana 45
18 03/05/2019 Mango 300
19 04/05/2019 APPLE 10
20 04/05/2019 Grapes 300
21 04/05/2019 Fish 120
22 05/05/2019 APPLE 12
23 05/05/2019 Fish 130
i miss some inputs every day,But i need to fill the gaps with previous row of the same "Type" on 30/04/2019 i missed "Banana & Mango" bu i need like
Id Date type quantity
1 29/04/2019 APPLE 2
2 29/04/2019 Banana 15
3 29/04/2019 Mango 100
4 29/04/2019 Grapes 50
5 29/04/2019 Fish 80
6 30/04/2019 APPLE 4
7 30/04/2019 Grapes 100
8 30/04/2019 Fish 90
9 30/04/2019 Banana 15
10 30/04/2019 Mango 100
actually last two rows are null but it should updated same on 29/04/2019
I think the easiets way might be this:
DECLARE #PDate DATE = SELECT TOP 1 Date FROM YourTable ORDER BY Date ASC --Previous Date
DECLARE #NDate DATE = SELECT TOP 1 Date FROM YourTable WHERE DATE>#PDate --Next Date
WHILE (#NDate IS NOT NULL)
BEGIN
WITH X AS
(
SELECT T1.Date AS Date1, T1.Type AS Type1, T1.Quantity AS Q1
T2.Date AS Date2, T2.Type AS Type2, T2.Quantity AS Q2
FROM YourTable T1
LEFT JOIN YourTable T2 ON T1.Type = T2.Type
WHERE T1.Date = #PDate AND T2.Date = #NDate
)
INSERT INTO YourTable (Date,Type,Quantity)
SELECT #NDate,Type1,Q1
WHERE X.Type2 IS NULL
SET #PDate = #NDate
SET #NDate = NULL -- If next result wasnt found this stays null for while condition
SET #NDate = SELECT TOP 1 Date FROM YourTable WHERE Date>#PDate
END
I think this is the way that may work and I wish so
( if there is any syntax or ... mistakes its because I didnt have SSMS installed to test. Sorry)
try this :
declare #date date
and for initiate #date you can use select #date=max(date) from table1 or pass static value set #date='02/01/2019'
and then find input
select input,max(date) as MaxDate into #temp
from table1
where input not in (select input from table1 where date=#date )
group by input
then :
select t.* from Table1 t join #temp on Table1.input=#temp.Input and Table1.date=#temp.MaxDate
OK, after the goal posts are settled, this is one method. Note that this solution builds both a Types and Dates dataset. Really the Types dataset should already exist somewhere in your database, and you should create a Calendar Table if you're going to be doing this type of work often.
Any way, I've left comments in the code for you. I've assumed you're using SQL Server 2012+, as 2008 is literally about to run out of support.
CREATE TABLE dbo.MyTable (ID int IDENTITY(1,1),
[date] date,
[type] varchar(10),
Quantity int);
INSERT INTO dbo.MyTable
SELECT CONVERT(date,[date],103),
RTRIM([Type]),
Quantity
FROM (VALUES('29/04/2019','APPLE ',2),
('29/04/2019','Banana',15),
('29/04/2019','Mango ',100),
('29/04/2019','Grapes',50),
('29/04/2019','Fish ',80),
('30/04/2019','APPLE ',4),
('30/04/2019','Grapes',100),
('30/04/2019','Fish ',90),
('01/05/2019','APPLE ',6),
('01/05/2019','Banana',30),
('01/05/2019','Grapes',150),
('01/05/2019','Fish ',100),
('02/05/2019','Mango ',200),
('02/05/2019','Grapes',200),
('02/05/2019','Fish ',110),
('03/05/2019','APPLE ',8),
('03/05/2019','Banana',45),
('03/05/2019','Mango ',300),
('04/05/2019','APPLE ',10),
('04/05/2019','Grapes',300),
('04/05/2019','Fish ',120),
('05/05/2019','APPLE ',12),
('05/05/2019','Fish ',130)) V([date],[Type],Quantity);
GO
--SELECT *
--FROM dbo.MyTable;
GO
--Create a calendar table
WITH N AS (
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
FROM N N1, N N2, N N3), --1000 days shuld be enough
Dates AS(
SELECT DATEADD(DAY, T.I, MIN(MT.[date])) AS [Date]
FROM Tally T
CROSS JOIN dbo.MyTable MT
GROUP BY T.I
HAVING DATEADD(DAY, T.I, MIN(MT.[date])) <= MAX([Date])),
--Get Types
Types AS (
SELECT DISTINCT [Type]
FROM dbo.MyTable MT),
--Create islands
Grps AS(
SELECT MT.ID,
D.[Date],
T.[Type],
MT.Quantity,
COUNT(MT.Quantity) OVER (PARTITION BY T.[Type] ORDER BY D.[date]
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Grp
FROM Dates D
CROSS JOIN Types T
LEFT JOIN dbo.MyTable MT ON D.[Date] = MT.[date]
AND T.[type] = MT.[type])
SELECT G.ID AS ID,
ROW_NUMBER() OVER (ORDER BY G.[Date], G.[Type]) AS RN,
G.[Date],
G.[Type],
MAX(G.Quantity) OVER (PARTITION BY G.[Type], G.Grp) AS Quantity
FROM Grps G
ORDER BY G.[Date],
G.[Type];
GO
DROP TABLE dbo.MyTable;
db<>fiddle
I think using cursor is a good option to insert your missing entries in the table. By cursor you will be able to check date wise missing types and insert them with the previous quantity.
You can also use this following script to find the missing records in your table. To create the script I consider the table name = 'add_missing_records'
SELECT AA.date AS [Date],
AA.type AS [Type],
BB.quantity AS [Original Quantity] ,
CASE
WHEN BB.quantity IS NULL THEN
(
SELECT quantity
FROM add_missing_records C
WHERE C.date = (
SELECT MAX([date])
FROM add_missing_records B
WHERE B.date < AA.date
AND B.type = AA.type
)
AND C.type = AA.type
)
ELSE BB.quantity
END AS [New Quantuty]
FROM (
SELECT date,type
FROM (
SELECT DISTINCT 'A' AS common,date
FROM add_missing_records
)A
FULL JOIN (
SELECT DISTINCT 'A' as common, type
FROM add_missing_records
)B
ON a.common = b.common
) AA
LEFT JOIN add_missing_records BB
ON AA.date = BB.date
AND AA.type = BB.type
WHERE BB.quantity IS NULL
ORDER BY 1,2

SQL Server: How to get the top 'N' max occurrences from each group

I have a below dataset and I am trying to get max occurrences of CID per each OID.
IF OBJECT_ID('TEMPDB..#SS',N'U') IS NOT NULL
DROP TABLE #SS
GO
SELECT * INTO #SS FROM (
SELECT 1 AS OID,501 AS CID
UNION ALL
SELECT 1 AS OID,503 AS CID
UNION ALL
SELECT 1 AS OID,502 AS CID
UNION ALL
SELECT 1 AS OID,501 AS CID
UNION ALL
SELECT 1 AS OID,501 AS CID
UNION ALL
SELECT 2 AS OID,502 AS CID
UNION ALL
SELECT 2 AS OID,502 AS CID
UNION ALL
SELECT 2 AS OID,502 AS CID
UNION ALL
SELECT 2 AS OID,501 AS CID
UNION ALL
SELECT 1 AS OID,503 AS CID
)A
GO
In above sample dataset, I need to get 2 CID per each OID which occurred maximum times. The expected result could be:
OID CID
1 501
1 503
2 501
2 502
This cannot be a duplicate to SQL Select top frequent records because I need this sub-queries and SQL-Server would not accept ORDER BY in sub-query and eventually I need a ranking function to solve my issue. Ranking function was not used in the link provided.
You can do this pretty easily utilizing ROW_NUMBER. Thanks for Tab Alleman for the clarification on your requirements.
select *
from
(
select *
, RowNum = ROW_NUMBER() over (partition by OID order by count(*) desc)
from #SS
group by OID
, CID
) x
where x.RowNum <= 2
order by x.OID
, x.CID

Select top 2 distinct for each id and date

I have a table like this :
Table1:
[Id] [TDate] [Score]
1 1.1.00 50
1 1.1.00 60
2 1.1.01 50
2 1.1.01 70
2 1.3.01 40
3 1.1.00 80
3 1.1.00 30
3 1.2.00 40
My desired output should be like this:
[ID] [TDate] [Score]
1 1.1.00 60
2 1.1.01 70
2 1.3.01 40
3 1.1.00 80
3 1.2.00 40
So fare, I have written this:
SELECT DISTINCT TOP 2 Id, TDate, Score
FROM
( SELECT Id, TDate, Score, ROW_NUMBER() over(partition by TDate order by Score) Od
FROM Table1
) A
WHERE A.Od = 1
ORDER BY Score
But it gives me :
[ID] [TDate] [Score]
2 1.1.01 70
3 1.1.00 80
of course I can do this:
"select top 2 ...where ID = 1"
and then:
union
`"Select top 2 ... where ID = 2"`
etc..
but I have a 100,000 of this..
Any way to generalize it to any Id?
Thank you.
WITH TOPTWO AS (
SELECT Id, TDate, Score, ROW_NUMBER()
over (
PARTITION BY TDate
order by SCORE
) AS RowNo
FROM [table_name]
)
SELECT * FROM TOPTWO WHERE RowNo <= 2
Your output doesn't make sense. Let me assume you want two rows per id. Then the query would look like:
SELECT TOP 2 Id, TDate, Score
FROM (SELECT Id, TDate, Score,
ROW_NUMBER() over (partition by id order by Score DESC) as seqnum
FROM Table1
) t
WHERE seqnum <= 2
ORDER BY Score;
Notes:
This assumes that you want two rows per id. Hence, id is in the PARTITION BY.
The WHERE now selects two rows per group in the PARTITION BY.
There is no need for SELECT DISTINCT in the outer query -- at least for this question.
Try this : Make partition by ID and TDate and sort by score in descending order
ROW_NUMBER() over(partition by ID,TDate order by Score DESC) Od
Complete script
WITH CTE AS(
SELECT *,
ROW_NUMBER() over(partition by ID,TDate order by Score DESC) RN
FROM TableName
)
SELECT *
FROM CTE
WHERE RN = 1
Unless I am missing something this can be done with a simple group by
First I prepare a temp table for testing :
declare #table table (ID int, TDate varchar(10), Score int)
insert into #Table values(1, '1.1.00', 50)
insert into #Table values(1, '1.1.00', 60)
insert into #Table values(2, '1.1.01', 50)
insert into #Table values(2, '1.1.01', 70)
insert into #Table values(2, '1.3.01', 40)
insert into #Table values(3, '1.1.00', 80)
insert into #Table values(3, '1.1.00', 30)
insert into #Table values(3, '1.2.00', 40)
Now lets do a select on this table
select ID, TDate, max(Score) as Score
from #table
group by ID, TDate
order by ID, TDate
The result is this :
ID TDate Score
1 1.1.00 60
2 1.1.01 70
2 1.3.01 40
3 1.1.00 80
3 1.2.00 40
So all you need to do is change #table to your table name and you are done

Extracting a (sampled) time series from an SQL DB

I have an MS SQL data base which contains values stored with their time stamps. So my result table looks like this:
date value
03.01.2016 11
19.01.2016 22
29.01.2016 33
17.02.2016 44
01.03.2016 55
06.03.2016 66
The time stamps don't really follow much of a pattern. Now, I need to extract weekly data from this: (sampled on Friday, for example)
date value
01.01.2016 11 // friday
08.01.2016 11 // next friday
15.01.2016 11
22.01.2016 22
29.01.2016 33
05.02.2016 33
12.02.2016 33
19.02.2016 44
26.02.2016 44
04.03.2016 55
11.03.2016 66
Is there a reasonable way to do this directly in T-SQL?
I could reformat the result table using a C# or Matlab program, but it seems a bit weird, because I seem to again query the result table...
You Could possibly use a CROSS JOIN or INNER JOIN. I would personally go with the INNER JOIN as its much more efficient.
SAMPLE DATA:
CREATE TABLE #Temp(SomeDate DATE
, SomeValue VARCHAR(10));
INSERT INTO #Temp(SomeDate
, SomeValue)
VALUES
('20160103'
, 11),
('20160119'
, 22),
('20160129'
, 33),
('20160217'
, 44),
('20160301'
, 55),
('20160306'
, 66)
QUERY USING CROSS JOIN:
;WITH T
AS (SELECT *
FROM #Temp),
D
AS (
SELECT SomeDate
, SomeValue
FROM #Temp AS A
UNION
SELECT DATEADD(day, 7, SomeDate)
, SomeValue
FROM #Temp AS B
UNION
SELECT DATEADD(day, 14, SomeDate)
, SomeValue
FROM #Temp AS C)
SELECT D.*
FROM T
CROSS JOIN D
WHERE T.SomeValue = D.SomeValue
ORDER BY SomeValue
, SomeDate;
RESULT:
QUERY USING INNER JOIN:
;WITH T
AS (SELECT *
FROM #Temp),
D
AS (
SELECT SomeDate
, SomeValue
FROM #Temp AS A
UNION
SELECT DATEADD(day, 7, SomeDate)
, SomeValue
FROM #Temp AS B
UNION
SELECT DATEADD(day, 14, SomeDate)
, SomeValue
FROM #Temp AS C)
SELECT D.*
FROM T
INNER JOIN D
ON T.SomeValue = D.SomeValue
ORDER BY SomeValue
, SomeDate;
RESULT:
This solution supports a maximum time window of 252 weeks from the first value time.
First row of your desired output is missing, because that friday is before the first value.
If needed, you can add it by mean of a UNION with a min of the table.
DECLARE #tbl TABLE ( [date] date, [value] int )
INSERT INTO #tbl
VALUES
('2016-01-03','11'),
('2016-01-19','22'),
('2016-01-29','33'),
('2016-02-17','44'),
('2016-03-01','55'),
('2016-03-06','66')
;WITH DATA
AS (
SELECT (S+P+Q) WeekNum, DATEADD( week, S + P + Q, MinDate ) Fridays, SubFri, [value]
FROM ( SELECT 1 S UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 ) A
CROSS JOIN ( SELECT 0 P UNION SELECT 7 UNION SELECT 14 UNION SELECT 21 UNION SELECT 28 UNION SELECT 35 ) B
CROSS JOIN ( SELECT 0 Q UNION SELECT 42 UNION SELECT 84 UNION SELECT 126 UNION SELECT 168 UNION SELECT 210 ) C
CROSS JOIN (
SELECT
min ( DATEADD( day, -8 - DATEPART(weekday,[date]), [date] ) ) MinDate,
max ( DATEADD( day, 13 - DATEPART(weekday,[date]), [date] ) ) MaxDate
FROM #tbl
) MD
LEFT JOIN ( SELECT DATEADD( day, 6 - DATEPART(weekday,[date]), [date] ) SubFri, [value] FROM #tbl ) Val
ON SubFri<=DATEADD( week, S + P + Q, MinDate )
WHERE DATEADD( week, S + P + Q, MinDate )<=MaxDate
)
SELECT DATA.Fridays, DATA.value
FROM DATA
INNER JOIN
(
SELECT Fridays, max(SubFri) MaxSubFri
FROM DATA
GROUP BY Fridays
) idx
ON DATA.Fridays=idx.Fridays
AND SubFri=MaxSubFri
ORDER BY Fridays
You should be able to use DATENAME to get all the records of a certain day:
SELECT *
FROM table
WHERE DATENAME(WEEKDAY, date) = 'Friday'
This causes a scan in the query plan though so it would be advisable to have another column with the day of the week and you could just select WHERE dayOfWeekCol = 'Friday'
I found my own solution, which I find more readable. I'm first using a WHILE loop to generate the dates I'm looking for. Then I 'join' these dates to the actual data table using an OUTER APPLY, which looks up 'last value before a specific date'. Here's the code:
-- prepare in-memory table
declare #tbl table ( [date] date, [value] int )
insert into #tbl
values
('2016-01-03','11'),
('2016-01-19','22'),
('2016-01-29','33'),
('2016-02-17','44'),
('2016-03-01','55'),
('2016-03-06','66')
-- query
declare #startDate date='2016-01-01';
declare #endDate date='2016-03-31';
with Fridays as (
select #startDate as fridayDate
union all
select dateadd(day,7,fridayDate) from Fridays where dateadd(day,7,fridayDate)<=#endDate
)
select *
from
Fridays f
outer apply (
select top(1) * from #tbl t
where f.fridayDate >= t.[date]
order by t.[value] desc
) as result
option (maxrecursion 10000)
Gives me:
fridayDate date value
---------- ---------- -----------
2016-01-01 NULL NULL
2016-01-08 2016-01-03 11
2016-01-15 2016-01-03 11
2016-01-22 2016-01-19 22
2016-01-29 2016-01-29 33
2016-02-05 2016-01-29 33
2016-02-12 2016-01-29 33
2016-02-19 2016-02-17 44
2016-02-26 2016-02-17 44
2016-03-04 2016-03-01 55
2016-03-11 2016-03-06 66
2016-03-18 2016-03-06 66
2016-03-25 2016-03-06 66
Thanks for everybody's ideas and support though!

How to get all numbers between a range

I have a table as below
Id RFrom RTo
.... ....... .....
1 10 14
1 22 25
2 100 102
2 176 180
I want to get all numbers between each RFrom and RTo for each Id. My expected result is as follows
Id NUMS
.... ......
1 10
1 11
1 12
1 13
1 14
1 22
1 23
1 24
1 25
2 100
2 101
2 102
2 176
2 177
2 178
2 179
2 180
Do I have to use cursor to achieve this?
Here is your sample table
SELECT * INTO #TEMP FROM
(
SELECT 1 ID, 10 RFROM, 14 RTO
UNION ALL
SELECT 1, 22, 25
UNION ALL
SELECT 2, 100, 102
UNION ALL
SELECT 2, 176, 180
)TAB
You need to use recursion for each Id to get the result
;WITH CTE AS
(
SELECT ID,RFROM RFROM1,RTO RTO1
FROM #TEMP
UNION ALL
SELECT T.ID,RFROM1+1,RTO1
FROM #TEMP T
JOIN CTE ON CTE.ID = T.ID
WHERE RFROM1 < RTO1
)
SELECT DISTINCT ID,RFROM1 NUMS
FROM CTE
SQL FIDDLE
Another option would be to use a numbers table with a join -- recursion can be time consuming.
There are several options to create a numbers table (I'd recommend creating a permanent one), but here's a temp one created with a common-table-expression:
with numberstable as (
select top 10000 row_number() over(order by t1.number) as number
from master..spt_values t1
cross join master..spt_values t2
)
select yt.id,
nt.number
from yourtable yt
join numberstable nt on nt.number between yt.rfrom and yt.rto
SQL Fiddle Demo
Create a tally table using stacked CTE which will have better performance when compared to recursive CTE
declare #min int
select #min= min(RFrom) from yourtable
;WITH e1(n) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
), -- 10
e2(n) AS (SELECT 1 FROM e1 CROSS JOIN e1 AS b), -- 10*10
e3(n) AS (SELECT 1 FROM e1 CROSS JOIN e2) -- 10*100
SELECT b.id,
a.n
FROM yourtable b
JOIN (SELECT n = Row_number()OVER (ORDER BY n)+ #min-1
FROM e3)a
ON a.n BETWEEN b.RFrom AND b.RTo
ORDER BY n;
Check here for info

Resources