动态table显示
Dynamic table display
我们的来源 table 来自其他用户,每次都有不同的列数。例如,今天 table 显示为:
Name Eye tail
-------------------
Dog Blue long
Cat Red short
但明天是:
Name eye tail skin
-------------------
Dog blue long white
Lion green short brown
我们的目标是将数据传输到这样一个固定的模式中table:
name property value
-------------------------
Dog Eye blue
Dog tail long
Dog skin white
Lion Eye green
Lion Tail short
Lion skin brown
为了实现这一点,现在我们使用半手动修改存储过程来进行这样的转换:
SELECT *
INTO #T
FROM table.original
INSERT INTO table.target(name, property, value)
SELECT name, property, value
FROM
--below is manually modified each time
(SELECT name = a.name, property = 'eye', value = a.eye
FROM #T a
UNION ALL
SELECT name, 'tail', tail
FROM #T
UNION ALL
SELECT name, 'skin', skin
FROM #T
UNION ALL
.........
)
有没有办法自动进行这种转换?我认为 FOR XML
可能会解决这个问题,但如何解决?
看起来很适合动态 UNPIVOT
:
DECLARE @columns NVARCHAR(MAX);
SELECT @columns = STUFF ((SELECT ',' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE [table_name] = 'tab'
AND column_name <> 'Name'
FOR XML PATH ('')),1,1,'');
DECLARE @sql NVARCHAR(MAX) =
N'INSERT INTO target(name, property, [value])
SELECT Name, property, [value]
FROM tab t
UNPIVOT
(
[value] FOR property IN (<placeholder>)
) unpvt;';
SET @sql = REPLACE(@sql, '<placeholder>', @columns);
EXEC dbo.sp_executesql
@sql;
SELECT *
FROM target;
输出:
╔═══════╦═══════════╦═══════╗
║ name ║ property ║ value ║
╠═══════╬═══════════╬═══════╣
║ Dog ║ eye ║ blue ║
║ Dog ║ tail ║ long ║
║ Dog ║ skin ║ white ║
║ Lion ║ eye ║ green ║
║ Lion ║ tail ║ short ║
║ Lion ║ skin ║ brown ║
╚═══════╩═══════════╩═══════╝
工作原理:
从输入的元数据中获取列列表 table 并将它们连接起来 [eye],[tail],[skin]
准备带有列占位符的主查询
用实际列名替换占位符
执行dynamic-SQL
勾选EAV
table
我们的来源 table 来自其他用户,每次都有不同的列数。例如,今天 table 显示为:
Name Eye tail
-------------------
Dog Blue long
Cat Red short
但明天是:
Name eye tail skin
-------------------
Dog blue long white
Lion green short brown
我们的目标是将数据传输到这样一个固定的模式中table:
name property value
-------------------------
Dog Eye blue
Dog tail long
Dog skin white
Lion Eye green
Lion Tail short
Lion skin brown
为了实现这一点,现在我们使用半手动修改存储过程来进行这样的转换:
SELECT *
INTO #T
FROM table.original
INSERT INTO table.target(name, property, value)
SELECT name, property, value
FROM
--below is manually modified each time
(SELECT name = a.name, property = 'eye', value = a.eye
FROM #T a
UNION ALL
SELECT name, 'tail', tail
FROM #T
UNION ALL
SELECT name, 'skin', skin
FROM #T
UNION ALL
.........
)
有没有办法自动进行这种转换?我认为 FOR XML
可能会解决这个问题,但如何解决?
看起来很适合动态 UNPIVOT
:
DECLARE @columns NVARCHAR(MAX);
SELECT @columns = STUFF ((SELECT ',' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE [table_name] = 'tab'
AND column_name <> 'Name'
FOR XML PATH ('')),1,1,'');
DECLARE @sql NVARCHAR(MAX) =
N'INSERT INTO target(name, property, [value])
SELECT Name, property, [value]
FROM tab t
UNPIVOT
(
[value] FOR property IN (<placeholder>)
) unpvt;';
SET @sql = REPLACE(@sql, '<placeholder>', @columns);
EXEC dbo.sp_executesql
@sql;
SELECT *
FROM target;
输出:
╔═══════╦═══════════╦═══════╗
║ name ║ property ║ value ║
╠═══════╬═══════════╬═══════╣
║ Dog ║ eye ║ blue ║
║ Dog ║ tail ║ long ║
║ Dog ║ skin ║ white ║
║ Lion ║ eye ║ green ║
║ Lion ║ tail ║ short ║
║ Lion ║ skin ║ brown ║
╚═══════╩═══════════╩═══════╝
工作原理:
从输入的元数据中获取列列表 table 并将它们连接起来
[eye],[tail],[skin]
准备带有列占位符的主查询
用实际列名替换占位符
执行dynamic-SQL
勾选
EAV
table