如何使用U-SQL使用上面的数据填充空白单元格

问题描述 投票:1回答:4

我有一个csv文件,我试图使用Azure Data Lake Analytics U-SQL处理。我是U-SQL的新手,所以请耐心等待。原始文件是半结构化的,我设法使用silent:true标志修复。现在它更结构化了,我想用上面单元格中的数据填充空单元格。

我的数据如下:CSV with empty cells

我的问题在于前四列中的空单元格。

第二行有数据,我想将其复制到它下面的空单元格(第3-5行)。需要将来自行7的数据向下复制到行8,将来自行9的数据向下复制到行10-13,将来自行14的数据复制到行15-18。

必须在不更改“已声明金额”列中的值的情况下执行此操作。

有没有人对如何在U-SQL中实现这一点有任何想法?

谢谢。

azure-data-lake u-sql
4个回答
3
投票

U-SQL通常是一种用于处理大型,与订单无关的数据的语言 - 这个问题不适合它

  • 输入数据中没有行排序标准。
  • 在U-SQL中重新创建输入行排序只能通过将提取限制为1个顶点来实现 - 这限制了输入数据的大小,并且与使用并行大数据处理语言有些不一致。

行集 - 基本的USQL构建块 - 是无序的逻辑数据容器。因此,原始输入中的行的顺序在您将其读入行集时就会丢失;你必须使用一些订购密钥在U-SQL中重新创建订单。

假设有这样的订购密钥,

@data = SELECT A, LAST_VALUE(Col == "" ? null : Col) OVER (ORDER BY Key ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Col FROM @input;

应该这样做,因为LAST_VALUE应该忽略空值。注 - USQL documentation实际上并没有指定是否忽略空值 - 它们应该按照一般的聚合/窗口函数约定,但这需要进行验证。

您的数据没有订购列 - 要创建一个,您需要

  1. 确保所有数据都由1个顶点处理 - [SqlUserDefinedExtractor(AtomicFileProcessing = true)]
  2. 在自定义提取程序中添加排序列。

对于您在上传之前可以在本地处理的大量数据,这可能过于复杂。


2
投票

LAG分析函数提供对当前行之前的给定物理偏移的行的访问。在SELECT表达式中使用此分析函数可将当前行中的值与上一行中的值进行比较。

https://msdn.microsoft.com/en-us/library/azure/mt791650.aspx


2
投票

另一种方法(LAST_VALUE对我不起作用):

如果您有一些行号或时间戳字段,那么没有问题

@tb1 = SELECT * FROM 
        ( VALUES
        (1, "Noah1"),
        (2, (string)null),
          (3, "Noah3"),
          (5, (string) null),
          (6, (string)null),
          (7, "Noah6"),
          (8, "Noah7")
        ) AS T(Timestamp, a);


@tb1 =
    SELECT Timestamp,
           [a],
           [a] != null && [a] != LEAD([a], 1) OVER(ORDER BY Timestamp ASC) AS aSwitch
    FROM @tb1;

@tb1 =
    SELECT Timestamp,
           [a],
           SUM(aSwitch ? 1 : 0) OVER(ORDER BY Timestamp ASC ROWS UNBOUNDED PRECEDING) AS aGrp
    FROM @tb1;

@tb1 =
    SELECT Timestamp,
           FIRST_VALUE([a]) OVER(PARTITION BY aGrp ORDER BY Timestamp ASC) AS aFilled
    FROM @tb1;

OUTPUT @tb1 TO "/test.csv" USING Outputters.Csv(outputHeader: true);

结果:

"Timestamp","aFilled"
1,"Noah1"
2,"Noah1"
3,"Noah3"
5,"Noah3"
6,"Noah3"
7,"Noah6"
8,"Noah7"

但是,如果你没有这样的领域该怎么办?在简单的情况下,您可以使用哑字段:

@tb1 = SELECT * FROM 
        ( VALUES
        ("Noah1"),
        ((string)null),
          ("Noah3"),
          ((string) null),
          ((string)null),
          ("Noah6"),
          ("Noah7")
        ) AS T(a);

@tb1 = SELECT 1 AS Timestamp,
              [a] 
            FROM  @tb1;

0
投票

我认为你可以通过使用U-SQL用户定义的运算符(UDO)来解决这个问题。在UDO中,您将逐行迭代,每当您获得具有空值的行时,请复制前一行的数据。

© www.soinside.com 2019 - 2024. All rights reserved.