如何转置 table SQL

How to transpose table SQL

我正在尝试转置 table,但我收到消息说列类型与其他列冲突。 这是解决方案

WITH CTE_Unpivoted as
( select ID, Fields, QuantityValue
from Bikes2 as s
UNPIVOT
(QuantityValue for Fields IN(ProductName, Country, Quantity)
)AS u
)
SELECT Fields, [1],[2],[3],[4],[5],[6],[7]
from CTE_Unpivoted AS u
PIVOT
(SUM(QuantityValue) for ID IN ([1],[2],[3],[4],[5],[6],[7])) AS p

这是数据

CREATE TABLE Bikes2
 (ID INT PRIMARY KEY IDENTITY,
 ProductName VARCHAR(50),
 Country VARCHAR(50),
 Quantity INT);
INSERT INTO Bikes2 VALUES ('Road Bike', 'USA', 128)
INSERT INTO Bikes2 VALUES ('Road Bike', 'Italy', 64)
INSERT INTO Bikes2 VALUES ('Electric Bike', 'USA', 257)
INSERT INTO Bikes2 VALUES ('Electric Bike', 'Italy', 143)
INSERT INTO Bikes2 VALUES ('Children Bicecle', 'USA', 386)
INSERT INTO Bikes2 VALUES ('Children Bicecle', 'Italy', 52)
INSERT INTO Bikes2 VALUES ('Road Bike', 'USA', 35)
SELECT * FROM Bikes2

如何正确执行此操作?有可能让它动态吗? 结果像这样

这种类型的重新格式化最好在应用层而不是在数据库中完成。原因有二:

  • A SQL 查询 returns 固定数量的列,而您似乎希望 table 中每行一列。所以你必须硬连接那个数字。
  • 每列只有一种类型,但您的数据包含字符串和数字。

也就是说,这是可能的。这是一种方法:

with b as (
      select b.*, row_number() over (order by id) as seqnum
      from bikes2 b
     )
select 'productname',
       max(case when seqnum = 1 then productname end),
       max(case when seqnum = 2 then productname end),
       max(case when seqnum = 3 then productname end),
       max(case when seqnum = 4 then productname end),
       max(case when seqnum = 5 then productname end),
       max(case when seqnum = 6 then productname end),
       max(case when seqnum = 7 then productname end)
from b
union all
select 'country',
       max(case when seqnum = 1 then country end),
       max(case when seqnum = 2 then country end),
       max(case when seqnum = 3 then country end),
       max(case when seqnum = 4 then country end),
       max(case when seqnum = 5 then country end),
       max(case when seqnum = 6 then country end),
       max(case when seqnum = 7 then country end)
from b
union all
select 'quantity',
       max(case when seqnum = 1 then cast(quantity as varchar(255)) end),
       max(case when seqnum = 2 then cast(quantity as varchar(255)) end),
       max(case when seqnum = 3 then cast(quantity as varchar(255)) end),
       max(case when seqnum = 4 then cast(quantity as varchar(255)) end),
       max(case when seqnum = 5 then cast(quantity as varchar(255)) end),
       max(case when seqnum = 6 then cast(quantity as varchar(255)) end),
       max(case when seqnum = 7 then cast(quantity as varchar(255)) end)
from b;

这可以简写为:

with b as (
      select b.*, row_number() over (order by id) as seqnum
      from bikes2 b
     )
select name,
       max(case when seqnum = 1 then val end),
       max(case when seqnum = 2 then val end),
       max(case when seqnum = 3 then val end),
       max(case when seqnum = 4 then val end),
       max(case when seqnum = 5 then val end),
       max(case when seqnum = 6 then val end),
       max(case when seqnum = 7 then val end)
from b cross apply
     (values (1, 'productname', productname),
             (2, 'country', country),
             (3, 'quantity', convert(varchar(255), quantity))
     ) v(ord, name, val)
group by name, ord
order by ord;

Here 是一个 db<>fiddle.