2017-06-15 43 views
0

我有一个csv文件,我尝试使用Azure Data Lake Analytics U-SQL进行处理。我对U-SQL相当陌生,所以请耐心等待。原始文件是我设法使用silent:true标志修复的半结构化文件。现在它更加结构化了,我想用上面单元格中的数据填充空单元格。如何用上述数据填充空白单元格使用U-SQL

我的数据是这样的: CSV with empty cells

我的问题在于,在第一四列空单元格。

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

这必须在不更改“金额声明”列中的值的情况下完成。

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

谢谢。

+0

谢谢大家的指导。我不是开发者,因此可能需要一段时间才能搞清楚,但我真诚地感谢所有的帮助。 – Ally

回答

0

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

+0

**行集没有顺序** - 它们是逻辑数据容器,类似于非重复哈希集合。序列化行的原始顺序不会隐式转移到行集(从而转移到UDO),它需要重新创建。请注意,只要您的方法*采用*顺序 - 任何行间顺序都必须在语言中明确指定。 – Nabeel

+0

**可以创建订单** - 您可以使用预设来维护单个顶点上的订单并处理数据,以确保其顺序工作。你可以通过这篇文章获得更多的帮助,如果你不明白它是如何工作的,请告诉我:https://blogs.msdn.microsoft.com/mrys/2016/06/08/how-do-i -combine-overlapping-ranges-using-u-sql -introducing -u-sql-reducer-udos/ – Jamil

+0

我在一年多前遇到过类似的情况,下面是对此的一些讨论:https://stackoverflow.com/questions/35624870/azure-data-lake-analytics-combine-overlapping-time-duration-using-u-sql希望它能帮助你学习。 – Jamil

2

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. 定制提取中添加排序列。

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

0

另一种方法(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; 
相关问题