SQL Server将Excel导入的日期数字转回日期格式及行转列需求
搞定Excel日期数字转SQL Server日期+UNPIVOT的方案
我明白你现在的困境:从Excel导数据时,日期列标题被SQL Server转成了像42845这样的数字,改Excel格式再导也没用,现在要通过视图用UNPIVOT把这些日期列转成行,同时得把数字转回正常日期。别担心,这事儿不难解决!
首先得搞懂:Excel里的日期数字本质是从1900年1月0日开始算的累计天数(不过Excel有个1900年是闰年的bug,所以实际要从1899-12-30开始计算,才能和SQL Server的日期对齐)。所以我们用DATEADD函数就能轻松转回来。
第一步:先搞定单个数字转日期
直接用这个公式就能把数字转成标准日期:
SELECT DATEADD(day, 42845, '1899-12-30') AS ConvertedDate; -- 算出来就是2017-06-01,对应Excel里的2017/6/1
第二步:结合UNPIVOT创建视图
假设你导入后的表叫ImportedData,结构大概是这样的:
| ID | Product | 42845 | 42846 | 42847 |
|---|---|---|---|---|
| 1 | 产品A | 100 | 150 | 200 |
| 2 | 产品B | 80 | 90 | 110 |
要把这些数字日期列转成行,同时转成日期格式,创建视图的SQL可以这么写:
CREATE VIEW vw_UnpivotedData AS SELECT ID, Product, -- 把数字列名转成日期 DATEADD(day, CAST(DateNumber AS INT), '1899-12-30') AS TransactionDate, Value FROM ImportedData UNPIVOT ( Value FOR DateNumber IN ([42845], [42846], [42847]) ) AS UnpivotResult;
第三步:如果日期列很多,用动态SQL自动处理
要是每次导入的日期列数量都不一样,硬写列名太麻烦,那就用动态SQL来自动生成UNPIVOT语句:
DECLARE @cols NVARCHAR(MAX), @query NVARCHAR(MAX); -- 自动获取所有数字格式的日期列名 SELECT @cols = STRING_AGG(QUOTENAME(name), ', ') FROM sys.columns WHERE object_id = OBJECT_ID('ImportedData') AND ISNUMERIC(name) = 1; -- 只挑数字列名 -- 构建动态创建视图的SQL SET @query = N' CREATE VIEW vw_DynamicUnpivotedData AS SELECT ID, Product, DATEADD(day, CAST(DateNumber AS INT), ''1899-12-30'') AS TransactionDate, Value FROM ImportedData UNPIVOT ( Value FOR DateNumber IN (' + @cols + N') ) AS UnpivotResult;'; -- 执行语句创建视图 EXEC sp_executesql @query;
小提醒
- 要确保那些数字列名确实是Excel转过来的日期数字,如果有其他数字列,得调整筛选条件。
- 要是你用的是苹果系统的Excel(默认1904日期系统),那起始日期要改成
1904-01-01,公式变成DATEADD(day, [日期数字], '1904-01-01'),不过大部分Windows环境的Excel都是1900系统,不用改。
内容的提问来源于stack exchange,提问作者Otshepeng Ditshego




