我需要使用 SSIS 加载 Excel 文件,其格式与此类似:
EmpID | 2024年8月 | 2024年9月 |
---|---|---|
12 | 100 | 350 |
并将其取消旋转,如下所示:
EmpID | 日期 | 价值 |
---|---|---|
12 | 2024年8月 | 100 |
12 | 2024年9月 | 350 |
总列数会不断变化。该数字可能会增加以同时保留时间段 11.2024-12.2026,但范围可能会更改为 09.2025-12.2026。我无法控制这些更改,我想找到一个自动化的解决方案,而不是使用新的文件格式手动更改解决方案。
是否可以在 SSIS 中逆透视时加载此类 Excel 文件?
我不太熟悉 SSIS 功能,也不熟悉 C#(如果可以通过脚本组件实现的话)。
我知道如何进行旋转本身,我的问题与如何通过不断变化的标题来做到这一点有关。我已经读过有关导入不带标头的文件并稍后将它们映射到数据库中的信息,但标头名称不可预测,因此我无法走这条路。
我不知道SSIS能做什么,但我相信T-SQL可以实现。
根据这个问题的答案,看来您可以使用
SELECT * INTO #ExcelStaging FROM OPOPENROWSET(...)
将Excel数据导入到临时表中,而无需提前知道列。然后,您可以查询结果表模式以提取感兴趣的列名称,以便您可以构建并执行动态 SQL 来执行 UNPIVOT
将导入的数据转换为所需的最终形式。
初始导入应该能够使用如下命令:
SELECT *
INTO #ExcelStaging
FROM OPENROWSET(
'Microsoft.ACE.OLEDB.12.0',
'Excel 12.0;Database=C:\Path\Name.xlsx;HDR=YES',
'SELECT * FROM [Sheet1$]'
)
但是,如果您需要使用变量或参数中包含的文件路径,我相信您需要使用动态 SQL(因为
OPENROWSET
似乎不接受表达式)。 比如:
DECLARE @FilePath NVARCHAR(MAX) = N'C:\Path\FileName.xlsx'
DECLARE @ImportSql = N'
SELECT *
INTO #ExcelStaging
FROM OPENROWSET(
''Microsoft.ACE.OLEDB.12.0'',
N''Excel 12.0;Database=' + REPLACE(@FilePath, '''', '''''') + N';HDR=YES'',
''SELECT * FROM [Sheet1$]''
)
'
PRINT @ImportSql
EXEC (@ImportSql)
上面的
REPLACE(..., '''', '''''')
处理可能包含撇号的文件路径值。
从那里,您可以查询导入的列并执行取消透视操作,如下所示:
-- Get list of column names like "MM.YYYY" and convert to
-- a list of the form "[MM.YYYY], [MM.YYYY], [MM.YYYY]"
DECLARE @DynamicColumnList NVARCHAR(MAX) = (
SELECT STRING_AGG(CAST(QUOTENAME(name) AS NVARCHAR(MAX)), ', ')
FROM tempdb.sys.columns
WHERE object_id = OBJECT_ID('tempdb..#ExcelStaging')
AND name LIKE '[0-9][0-9].[0-9][0-9][0-9][0-9]' -- Names like "MM.YYYY"
)
-- Dynamic SQL to select, unpivot, and insert the imported data into the target table
DECLARE @UnpivotSql NVARCHAR(MAX) = '
INSERT INTO ImportResults (EmpId, Date, Value)
SELECT U.EmpId, U.Date, U.Value
FROM (
SELECT EmpID, ' + @DynamicColumnList + '
FROM #ExcelStaging
) E
UNPIVOT (
Value
FOR Date IN (' + @DynamicColumnList + ')
) U
'
-- Execute
PRINT @UnpivotSql
EXEC (@UnpivotSql )
-- Show results
SELECT *
FROM ImportResults
ORDER BY EmpId, Date
对于表格的导入数据:
EmpID | 垃圾 | 2024年8月 | 2024年9月 | 2024年10月 |
---|---|---|---|---|
12 | X | 100 | 350 | 400 |
13 | 是 | 30 | 40 | 50 |
以上将产生以下结果:
EmpID | 日期 | 价值 |
---|---|---|
12 | 2024年8月 | 100 |
12 | 2024年9月 | 350 |
12 | 2024年10月 | 400 |
13 | 2024年8月 | 30 |
13 | 2024年9月 | 40 |
13 | 2024年10月 | 50 |
请参阅 this db<>fiddle 以获取此过程的部分演示。 fiddle 环境不允许导入实际的 Excel 文件。
我将把它留给您以及其他一些有帮助的贡献者来处理将其适应 SSIS 包的细节。 (正如我之前提到的,我没有这方面的专业知识。)
我欢迎对这篇文章进行任何更正或其他改进。随意直接编辑。