SQL: Real Transpose

2020-01-29 09:30发布

I know about pivot and unpivot. That is not what I want. Pivot and unpivot aggregate data, but that is not what I want.

Think of a table as a matrix (linear algebra). If I start with an m x n matrix, I want to convert that matrix (table) into an n x m matrix. I want a true TRANSPOSE.

How can I do this in SQL?

For example if I have:

1  2  3
1  2  4
6  7  8
3  2  1
3  9  1

then the result should be:

1  1  6  3  3
2  2  7  2  9
3  4  8  1  1

Notice that the number of rows becomes the number of columns, and vice versa. Also notice that I have not grouped or aggregated any of the data. Every single value present in the source is present in the result, and their x-y coordinates have been swapped.

1条回答
Bombasti
2楼-- · 2020-01-29 09:46

I am unsure why you think you cannot accomplish this with an UNPIVOT and a PIVOT:

select [1], [2], [3], [4], [5]
from 
(
  select *
  from
  (
    select col1, col2, col3,
      row_number() over(order by col1) rn
    from yourtable
  ) x
  unpivot
  (
    val for col in (col1, col2, col3)
  ) u
) x1
pivot
(
  max(val)
  for rn in ([1], [2], [3], [4], [5])
) p

See SQL Fiddle with Demo. This could also be performed dynamically if needed.

Edit, if the column order needs to be kept, then you can use something like this, which applies the row_number() without using a order by on one of the columns in your table (here is an article about using non-deterministic row numbers):

select [1], [2], [3], [4], [5]
from 
(
  select *
  from
  (
    select col1, col2, col3,
      row_number() 
        over(order by (select 1)) rn
    from yourtable
  ) x
  unpivot
  (
    val for col in (col1, col2, col3)
  ) u
) x1
pivot
(
  max(val)
  for rn in ([1], [2], [3], [4], [5])
) p;

See SQL Fiddle with Demo

查看更多
登录 后发表回答