我正在尝试将具有多行和多列的表取消。需要将每行扩展为包含特定列的2行,并且需要重命名列名称,并根据所选列添加新列!
我包括样本数据之前和之后以及设置数据的脚本。
CREATE TABLE #tmpProducts (
ProductId INT,
ProductName nVARCHAR(100),
B2B_GrossRevenue DECIMAL(10,2),
B2B_DirectCost DECIMAL(10,2),
B2B_NetRevenue DECIMAL(10,2),
B2C_GrossRevenue DECIMAL(10,2),
B2C_DirectCost DECIMAL(10,2),
B2C_NetRevenue DECIMAL(10,2)
)
INSERT INTO #tmpProducts SELECT 1, 'Product1',1545.00,406.25,1138.75,195.00,35.10,159.90
INSERT INTO #tmpProducts SELECT 2, 'Product2',902.00,189.00,713.00,3280.00,590.40,2689.60
INSERT INTO #tmpProducts SELECT 3, 'Product3',15665.00,3988.39,11676.61,6247.00,1124.46,5122.54
INSERT INTO #tmpProducts SELECT 4, 'Product4',736.00,196.16,539.84,2395.00,431.10,1963.90
SELECT * FROM #tmpProducts
DROP TABLE #tmpProducts
CREATE TABLE #tmpProducts2 (
ProductId INT,
ProductName nVARCHAR(100),
[Type] nVARCHAR(3),
GrossRevenue DECIMAL(10,2),
DirectCost DECIMAL(10,2),
NetRevenue DECIMAL(10,2)
)
INSERT INTO #tmpProducts2 SELECT 1, 'Product1','B2B',1545.00,406.25,1138.75
INSERT INTO #tmpProducts2 SELECT 1, 'Product1','B2C',195.00,35.10,159.90
INSERT INTO #tmpProducts2 SELECT 2, 'Product2','B2B',902.00,189.00,713.00
INSERT INTO #tmpProducts2 SELECT 2, 'Product2','B2C',3280.00,590.40,2689.60
INSERT INTO #tmpProducts2 SELECT 3, 'Product3','B2B',15665.00,3988.39,11676.61
INSERT INTO #tmpProducts2 SELECT 3, 'Product3','B2C',6247.00,1124.46,5122.54
INSERT INTO #tmpProducts2 SELECT 4, 'Product4','B2B',736.00,196.16,539.84
INSERT INTO #tmpProducts2 SELECT 4, 'Product4','B2C',2395.00,431.10,1963.90
SELECT * FROM #tmpProducts2
DROP TABLE #tmpProducts2
我试过这个,但我无法通过第二列,我不知道如何添加一个具有特定文本的新列,(可能是动态sql,但试图避免这种情况,如果可能的话)
这是我尝试的开始,非常感谢任何帮助。
SELECT ProductId, ProductName,GrossRevenue
FROM (
SELECT ProductId, ProductName, B2B_GrossRevenue,B2C_GrossRevenue FROM #tmpProducts
) as t
UNPIVOT ( GrossRevenue for test IN (B2B_GrossRevenue,B2C_GrossRevenue)) AS unpvt
答案 0 :(得分:5)
你只是保持不动摇
SELECT ProductId,ProductName, Substring(col1,1,3) as type, GrossRevenue, DirectCost, NetRevenue
FROM (
SELECT * FROM #tmpProducts
) as t
UNPIVOT ( GrossRevenue for col1 IN (B2B_GrossRevenue,B2C_GrossRevenue)) AS unpvt
unpivot ( DirectCost for col2 in (B2b_DirectCost, B2c_DirectCost)) up2
unpivot ( NetRevenue for col3 in (B2b_NetRevenue, B2c_NetRevenue)) up3
where SUBSTRING(col1,1,3)=SUBSTRING(col2,1,3)
and SUBSTRING(col1,1,3)=SUBSTRING(col3,1,3)
并加入col列以过滤掉不匹配
答案 1 :(得分:2)
以下是使用Dynamic SQL执行此操作的方法。这将允许您在执行时获取所有列。然后,如果您获得任何数据更改,则无需更改查询。这同时适用于UNPIVOT
和PIVOT
:
DECLARE @colsUnPivot AS NVARCHAR(MAX),
@colsPivot AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
SET @colsUnPivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('tmpProducts') and
C.name like 'B2%'
for xml path('')), 1, 1, '')
SET @colsPivot = stuff((select DISTINCT ','+quotename(right((C.name), len(C.name)-4))
from sys.columns as C
where C.object_id = object_id('tmpProducts') and
C.name like 'B2%'
for xml path('')), 1, 1, '')
set @query
= ' SELECT ProductId, ProductName, [type], ' + @colsPivot +'
FROM
(
SELECT ProductId, ProductName, substring(field, 1, 3) [type]
, value, right((field), len(field)-4) as col
from tmpProducts
unpivot
(
value
for field in (' + @colsUnPivot + ')
) unpvt
) x
PIVOT
(
sum(value)
FOR col IN (' + @colsPivot +')
)p'
execute(@query)
答案 2 :(得分:0)
如果您有多个想要转移的群组,您也可以这样做:
Select *
from table
unpivot include nulls ( (test_name, test_date) for col_nm in ( (test1, date1) as 'test_val1'
,(test2, date2) as 'test_val2'
,(test3, date3) as 'test_val3'
)
)