Create two columns from one, based on two different WHERE clauses
;WITH x AS 
(
  SELECT TOP (1000) Value, row_num = ROW_NUMBER() OVER (ORDER BY Value)
    FROM OnlineQnres.dbo.tmp_oDataSets
    WHERE VariableID = '1'
), y AS
(
  SELECT TOP (1000) Value, row_num = ROW_NUMBER() OVER (ORDER BY Value)
    FROM OnlineQnres.dbo.tmp_oDataSets
    WHERE VariableID = '4'
)
SELECT val1 = x.Value, val2 = y.Value
FROM x INNER JOIN y
ON x.row_num = y.row_num;


As I stated in a comment, for this correlation to be meaningful, you need to define how the ROW_NUMBER() is calculated (or indicate how these two sets of values are related). In this case it will correlate the smallest value for variableID = 1 with the smallest value for variableID = 2, the 2nd smallest value for variableID = 1 with the 2nd smallest value for variableID = 2, etc.

Also, as others noted, to get predictable results, you need to define TOP (1000) with a separate ORDER BY.

Essentially, if you have these rows in the table, and pretend you are only looking for two of each variableID:

VariableID    Value
----------    -------
1             foo
1             bar
4             mort
4             splunge


What does the result look like? Should it be:

val1    val2
------  -------
foo     mort
bar     splunge


If so, why? If not, why not? Or should it be:

val1    val2
------  -------
foo     splunge
bar     mort


If so, why? If not, why not? Or should it be:

val1    val2
------  -------
foo     NULL
bar     NULL
NULL    mort
NULL    splunge


Or something else entirely? 

There are other query approaches too, but they depend on your requirements, and how the rows are linked other than the fact that they are "any" row that match the WHERE clauses.

Flimsy requirements lead to flimsy answers, sorry.