You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用U-SQL读取未知列数Excel时消除最后列值重复问题(Azure Data Lake)

你现在面临两个小问题:一是oh22is的ExcelExtractor会用最后一个有数据列的值自动填充后续空列,二是需要把当前的宽表转成Year/Month/SUM的窄表格式。我给你梳理一套可行的解决步骤:

第一步:标记行类型并拆解所有列

首先我们得先给每行打上类型标签(区分SUM汇总行、年份行、月份行),然后把所有数据列转成「列名-值」的键值对形式,方便后续过滤和聚合:

USE DATABASE master;
REFERENCE ASSEMBLY [DocumentFormat.OpenXml];
REFERENCE ASSEMBLY [oh22is.Analytics.Formats];
DECLARE @ExcelFile = @SourceFolderPath+@SourceFileName;

-- 提取所有列并标记行的类型
@ResourcesWithRowType =
    SELECT *,
           CASE [A]
               WHEN "SUM:" THEN "SumRow"
               WHEN "年份" THEN "YearRow"
               WHEN "月份" THEN "MonthRow"
               ELSE "Other" -- 按需处理其他可能的行,比如表头行
           END AS RowType
    FROM @ExcelFile
    USING new oh22is.Analytics.Formats.ExcelExtractor("Ark1");

-- 把B到HZ的所有数据列拆成键值对(这里需要手动列出所有列,U-SQL静态类型要求必须明确)
@Unpivoted =
    SELECT RowType,
           ColumnName,
           ColumnValue
    FROM @ResourcesWithRowType
    CROSS APPLY (
        VALUES
            ("B", [B]), ("C", [C]), ("D", [D]), 
            -- 中间省略其他列,直到列出("AM", [AM]), ("AN", [AN]), ..., ("HZ", [HZ])
            ("AM", [AM]), ("AN", [AN]), ..., ("HZ", [HZ])
    ) AS Columns(ColumnName, ColumnValue);

第二步:过滤掉重复填充的列

核心思路是:找出那些所有行的值都和最后一个有效列(你的例子里是AM列)完全相同的列,这些就是被重复填充的无效列,直接排除:

-- 先获取AM列(最后一个有真实数据的列)在各行的值
@AMColumnValues =
    SELECT RowType, ColumnValue AS AMValue
    FROM @Unpivoted
    WHERE ColumnName == "AM";

-- 筛选有效列:要么是AM列本身,要么至少有一行的值和AM列不一样
@ValidColumnNames =
    SELECT DISTINCT u.ColumnName
    FROM @Unpivoted u
    JOIN @AMColumnValues am ON u.RowType == am.RowType
    WHERE u.ColumnName == "AM" OR u.ColumnValue != am.AMValue;

-- 只保留有效列的数据
@FilteredUnpivoted =
    SELECT u.RowType, u.ColumnName, u.ColumnValue
    FROM @Unpivoted u
    JOIN @ValidColumnNames vc ON u.ColumnName == vc.ColumnName;

第三步:聚合生成目标窄表

现在我们已经有了干净的键值对数据,接下来按列名分组,把同一列对应的年份、月份、SUM值聚合到一行:

-- 转成Year/Month/SUM的目标结构
@FinalResult =
    SELECT 
        MAX(CASE WHEN RowType == "YearRow" THEN ColumnValue END) AS Year,
        MAX(CASE WHEN RowType == "MonthRow" THEN ColumnValue END) AS Month,
        MAX(CASE WHEN RowType == "SumRow" THEN ColumnValue END) AS SUM
    FROM @FilteredUnpivoted
    GROUP BY ColumnName;

-- 输出最终结果
OUTPUT @FinalResult TO "/FinalPivotedResult.csv" USING Outputters.Csv(quoting: false);

额外小贴士

  • 如果后续Excel的有效列数量变化(比如下个月新增到AO列),你不需要修改代码里的AM判断逻辑——这套代码会自动识别所有和最后一个有差异的列,只要某列存在至少一行的值和当前最后一个有效列不同,就会被保留。
  • 关于ExcelExtractor的重复填充问题,你可以查一下该库的文档,看看有没有参数能设置只提取有实际数据的列,这样能避免一开始就提取大量空列,提升运行效率。

内容的提问来源于stack exchange,提问作者Ville Lehtisaari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 13:52:56