C# USQL-如何选择USQL中两个字符串行之间的所有行
以下是我的完整任务描述: 我必须使用u-sql从多个文件中提取数据,并将其输出到csv文件中。每个输入文件都包含基于某些字符串行的多个报告(“开始…”和“结束…”用作报告分隔符)。以下是单个源(输入)文件的示例(数据格式): 所以现在我的问题是如何获取所有文件的“开始…”和“结束…”行之间的记录 我希望在结尾有这样的内容:C# USQL-如何选择USQL中两个字符串行之间的所有行,c#,azure-sql-database,azure-data-lake,u-sql,C#,Azure Sql Database,Azure Data Lake,U Sql,以下是我的完整任务描述: 我必须使用u-sql从多个文件中提取数据,并将其输出到csv文件中。每个输入文件都包含基于某些字符串行的多个报告(“开始…”和“结束…”用作报告分隔符)。以下是单个源(输入)文件的示例(数据格式): 所以现在我的问题是如何获取所有文件的“开始…”和“结束…”行之间的记录 我希望在结尾有这样的内容: @dailyAccountResult = [select all rows between "START OF DAILY ACCOUNT" and "END OF DAI
@dailyAccountResult = [select all rows between "START OF DAILY ACCOUNT" and "END OF DAILY ACCOUNT" rows]
@ledgerBalanceResult = [select all rows between "START OF LEDGER BALANCE" and "END OF LEDGER BALANCE" rows]
@dailySummaryReportResult = [select all rows between "START OF DAILY SUMMARY REPORT" and "END OF DAILY SUMMARY REPORT" rows]
我需要为此编写自定义提取器吗?如果是,请建议我如何操作。我认为使用普通U-SQL而不使用自定义提取器是可能的。我根据您的建议创建了一个简单的示例:
试试看,让我知道你进展如何。要问的相关问题:
- 绝对不是!有关确认信息,请参阅摘录文档(msdn.microsoft.com/en-us/library/azure mt621320.aspx)
- 建议数据原子性的通用单位是“行”(行结构文件),这是数据上传本身的属性
- 根据,
确保由一个实例按顺序处理整个输入,这就足够了,并且在这种情况下可能可行,具体取决于输入大小[SqlUserDefinedExtractor(AtomicFileProcessing=true)]
- 不行集是无序的概念-可以将它们视为非重复数据消除哈希集
不希望保留原始的行顺序(即使对某些输入是这样,这是实现细节,不保证语义行为)。var input=newhashset(File.ReadLines(@In_Data)); File.writeAllines(@Out\u NewData,input)
行集也是如此-当数据转换为行集时,行的输入顺序丢失(不保证)。因此,尝试使用ROW_NUMBER()是徒劳的-在调用ROW_NUMBER()时,没有顺序可以保留。使用ROW_NUMBER()的唯一方法是,如果行集有某个键,其排序顺序可以重新创建行的原始顺序
- 它使用原子文件处理,或
- 您可以找到一种方法来保证在开始…结束序列之间不会发生数据拆分。AFAIK没有办法做到这一点(除非将整个序列预处理为预上传行)
您可以选择将所有逻辑包含在自定义提取器中,或者只需添加一个带编号的列来模拟行号,并使用本机U-Sql进行逻辑处理。仍不清楚。至少对我来说。你的文件有多大?非常感谢你的帮助。它按预期工作。:)有趣的评论@Nabeel。最好能得到一些关于何时发生这种情况的进一步信息,例如250MB的数据块限制。您有任何进一步的信息吗?从我到目前为止看到的文档来看,发生的时间似乎是实现细节(目前可能是250MB),发生的时间(语义保证)似乎是您有>1行的任何时候。如果需要,您可以在自定义提取器中定义行分隔符,但这会限制格式;这里的格式不是以行分隔的格式。
@dailyAccountResult = [select all rows between "START OF DAILY ACCOUNT" and "END OF DAILY ACCOUNT" rows]
@ledgerBalanceResult = [select all rows between "START OF LEDGER BALANCE" and "END OF LEDGER BALANCE" rows]
@dailySummaryReportResult = [select all rows between "START OF DAILY SUMMARY REPORT" and "END OF DAILY SUMMARY REPORT" rows]
// Get raw input
@input =
EXTRACT rawData string
FROM "/input/input36.txt"
USING Extractors.Tsv();
// Add a row number and break out the section;
// Get all [START OF ...] and [END OF ...] blocks and pair them.
// !!WARNING code assumes there are no duplicate sections, ie can not be more than one DAILY ACCOUNT section for example
@working =
SELECT ROW_NUMBER() OVER() AS rn,
System.Text.RegularExpressions.Regex.Match(rawData, "(START OF|END OF) (?<sectionName>.+)").Groups["sectionName"].ToString() AS sectionName,
*
FROM @input;
// Work out the section boundaries
@sections =
SELECT sectionName,
MIN(rn) AS startRn,
MAX(rn) AS endRn,
COUNT( * ) AS records
FROM @working
WHERE sectionName != ""
GROUP BY sectionName;
// Create the output
@output =
SELECT s.sectionName,
i.rn == s.startRn ? 1 : 0 AS isStartSection,
i.rn == s.endRn ? 1 : 0 AS isEndSection,
i.rawData
FROM @sections AS s
CROSS JOIN
@working AS i
WHERE i.rn BETWEEN s.startRn AND s.endRn;
// Output the file
OUTPUT @output
TO "/output/output.txt"
USING Outputters.Tsv(quoting : false);
@dailyAccount =
SELECT rawData
FROM @output
WHERE sectionName == "DAILY ACCOUNT"
AND isStartSection == 0
AND isEndSection == 0;