【问题标题】:How to output multiple files dynamically using U-SQL custom Extractors?如何使用 U-SQL 自定义提取器动态输出多个文件?
【发布时间】:2017-07-19 12:46:21
【问题描述】:

我创建了一个从多个文件中读取数据的 U-SQL 查询。现在我必须在其他文件夹中的多个文件中输出数据。我有下面的例子,

U-SQL Output in Azure Data Lake

使用下面的脚本,

        DECLARE @storagePath string = @"E:\";
        DECLARE @inputFileSetName string = @"dbo.file{*}.tsv"; 
        DECLARE @outputFileName string = @"dbo.files.csv";

        DECLARE @input string = String.Concat(@storagePath, 
        @inputFileSetName);
        DECLARE @output = string.Concat(@storagePath, @outputFileName);
        @searchlog =
        EXTRACT Id string,
        Name string,
        Address string

        FROM @input
        USING new USQLApplication3.SampleExtractor(Encoding.UTF8);
        @transactions =
        SELECT *,
        ROW_NUMBER() OVER(PARTITION BY Id ORDER BY Id DESC) AS 
        RowNumber_12345
        FROM @searchlog;

       @result =
       SELECT EXTRACT Id,
        Name,
        Address 
       FROM @transactions
       WHERE RowNumber_12345 == 1;

       OUTPUT @result 
       TO @output
       USING Outputters.Csv(encoding : Encoding.UTF8, quoting : false);

以下是自定义提取器的 C# 代码,

public class SampleExtractor : IExtractor
{
    private Encoding _encoding;
    private byte[] _row_delim;
    private char _col_delim;

    public SampleExtractor(Encoding encoding, string row_delim = "\n", char col_delim = '\t')
    {
        this._encoding = ((encoding == null) ? Encoding.UTF8 : encoding);
        this._row_delim = this._encoding.GetBytes(row_delim);
        this._col_delim = col_delim;
    }

    public override IEnumerable<IRow> Extract(IUnstructuredReader input, IUpdatableRow output)
    {
        string line;
        //Read the input line by line
        foreach (Stream current in input.Split(_encoding.GetBytes("\n")))
        {
            using (StreamReader streamReader = new StreamReader(current, this._encoding))
            {
                line = streamReader.ReadToEnd().Trim();
                //Split the input by the column delimiter
                string[] parts = line.Split(this._col_delim);
                foreach (string part in parts)
                {
                    string res = part;
                    if (res != null)
                    {
                        res = "\"" + res.Replace("\"", "\"\"") + "\"";
                    }
                    output.Set<string>(count, res);
                }

            }
            yield return output.AsReadOnly();

        }
       yield break;
    }
}

如何在输出时动态创建多个文件?截至目前,它只创建一个文件。

已编辑:

我也尝试过在单个 u-sql 脚本中使用多个输出,

      @x = SELECT * FROM (VALUES( "A", 10, 20), ("A", 11, 21), ("B", 10, 30), ("B", 100, 200)) AS T(name, value1, value2);

     // Generate the script to do partitioned output based on name column:
     DECLARE @out string ="E:/genscript.usql";
     @stmts = 
         SELECT "@res=SELECT value1, value2 FROM @x WHERE name == 
         \""+name+"\"; 
     OUTPUT 
          @res TO \"E:/"+name+".csv\" USING Outputters.Csv();" AS output 
          FROM (SELECT DISTINCT name FROM @x) AS x;

     OUTPUT @stmts TO @out
           USING Outputters.Text(delimiter:' ', quoting:false);

     @path = EXTRACT path string FROM @out USING Extractors.Text() ;
     OUTPUT @path  TO "E:/{*}.usql" 
           USING Outputters.Text(delimiter:' ', quoting:false);

但它显示以下错误,

严重性代码描述项目文件行抑制状态 错误 E_CSC_USER_READFROMPREVIOUSOUTPUT:EXTRACT 语句从位置 E:\genscript.usql 读取/引用,该位置是先前 OUTPUT 语句的目标。 描述: 编译器不支持在单个作业中输出到同一个文件,然后从同一个文件中读取/引用。 解决: 请制作一项作业以输出到文件,并制作一项不同的作业以读取/引用同一文件。

我现在应该怎么做才能从单个 u-sql 输出多个文件,或者如何从当前 u-sql 脚本访问另一个 u-sql 脚本文件?

【问题讨论】:

  • 您可能需要创建一个一次只执行 1 条记录的 JOB。然后参数化它,每条记录都会有一个输出

标签: c# azure azure-data-lake u-sql


【解决方案1】:

您可以简单地使用多个OUTPUT 命令,例如

OUTPUT @result1
TO @output1
USING Outputters.Csv(encoding : Encoding.UTF8, quoting : false);

OUTPUT @result2
TO @output2
USING Outputters.Csv(encoding : Encoding.UTF8, quoting : false);
...

U-SQL 不直接支持动态 U-SQL,但有一些方法可以做到。两种示例方法是herehere

【讨论】:

  • 你好,我要根据输入文件的行数动态创建。
  • 他们没有得到“/output/dynamic.usql”查询
  • 那么它将如何处理数据
  • Arron:示例中的脚本正在创建另一个 U-SQL 脚本。因此,您可以通过首先运行生成脚本来编排执行,然后下载生成的脚本(例如 dynamic.usql),然后运行该脚本。请注意,输出到多个文件的功能仍在开发中。
【解决方案2】:

截至 2020 年,这是在功能预览标志 DataPartitionedOutput:on 之后发布的

SET @@FeaturePreviews = "DataPartitionedOutput:on";


@rows =
EXTRACT 
Firstname string,
Lastname string,
Score string
FROM "/input/a.csv"
USING Extractors.Csv(skipFirstNRows:1);


OUTPUT @rows
TO @"output/{Score}.csv"
USING Outputters.Csv();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    • 1970-01-01
    相关资源
    最近更新 更多