The principle is that you need to select a contiguous list of numbers and then match them to the data you have in your table.
Here is your data
declare @demo table ([week] int, [year] int, platformname nvarchar(30), operatingsystem nvarchar(30))
insert into @demo ([week], [year], platformname, operatingsystem) values
(1, 2018, 'sql', 'w7'),(2, 2018, 'sql', 'w7'),
(5, 2018, 'sql', 'w7'),(6, 2018, 'sql', 'w7')
As you say there is a gap where 3 and 4 should be.
Here is a neat and efficient way of generating all the numbers you want
select * from
(select top (@top) row_number() over (order by a.object_id) AS seqNum
from sys.columns a) as nums
That query uses the system table sys.columns just because I know there is going to be some data in there, probably quite a lot depending on my database schema. In my case there are 1167 columns in my database, but if that isn't enough you can use a
cross join
to the same table to get even more numbers - 1361889 in my case i.e. 1167 x 1167
So I didn't end up with 1361883 empty rows in my results I've limited the number of numbers I want by using
top (@top)
where
declare @top int = (select max([week]) from @demo)
I could just as easily have hard-coded this to 10 for example.
Combine the two queries with a LEFT OUTER join using the numbers table as the left table and your data table as the right table i.e.
select nums.seqNum, [year], platformname, operatingsystem
from
(select top (@top) row_number() over (order by a.object_id) AS seqNum
from sys.columns a cross join sys.columns b) as nums
left outer join @demo on seqNum = [week]
which gives the results
seqNum year platformname operatingsystem
1 2018 sql w7
2 2018 sql w7
3 NULL NULL NULL
4 NULL NULL NULL
5 2018 sql w7
6 2018 sql w7
You'll have to decide what to do with the NULL values