Gabriele's answer 在我看来还不错。
但是,如果您发现自己处于这样一种情况,即您在许多建筑物中拥有大量数据,以至于您可以将任何单个建筑物的行数据存储在内存中,但不能存储所有数据,那么我会倾向于使用稍微不同的方法。
在此示例作业中,我使用 MySQL 数据库组件只是因为我碰巧有一个本地 MySQL 数据库,但有关此作业的所有内容也适用于 Oracle 或 MS SQL Server:
在这种情况下,一开始我们使用 tMySqlConnection 组件打开到数据库的连接。剩下的 2 个数据库组件(tMySqlInput 和 tMySqlRow)然后使用共享连接详细信息。
我们首先使用 tMySqlInput 中的以下查询获取数据库中的建筑物列表:
"SELECT DISTINCT building
FROM filesplittest"
这会返回每个不同的建筑物。
然后我们遍历每个建筑物,这样我们就可以在内存中只保留该特定建筑物的记录,以便在接下来的工作中使用。
然后,我们使用 tMySqlRow 组件通过准备好的语句为特定的迭代构建拉取数据。我使用的示例查询如下所示:
"SELECT building, foo, bar
FROM FileSplitTest
WHERE building = ?"
然后我们在高级设置中配置prepared statement:
我说过第一个参数(参数索引 = 1)是我们之前检索到的建筑值,并且 tFlowToIterate 帮助我们推送到 globalMap,因此我们在这种情况下使用 ((String)globalMap.get("row6.building")) 从那里检索它(它是第 6 行流中的“建筑”列)。
当使用准备好的语句时,您需要将数据作为记录集对象检索,因此您需要像这样设置 tMySqlRow 的架构:
然后我们使用 tParseRecordSet 组件对其进行解析:
使用适合此示例的架构:
然后我们需要遍历这组数据,将其附加到适当命名的 CSV。为此,我们使用另一个 tFlowToIterate 组件,并通过 tFixedFlowInput 组件绕了一个稍微烦人的弯路,在将每条记录的数据从 globalMap 中读取出来,然后再将其传递给 tFileOutputDelimited:
最后我们将其追加到以建筑物命名的 CSV:
请注意附加复选框已选中,否则作业的每次迭代都会覆盖前一个。我们还通过 building 列中的值命名文件。
正如 Gabriele 所提到的,如果您的数据在任何时候都可以很好地放入内存中,您可以通过将数据读入 tHashOutput 组件然后过滤散列中的数据来简化工作:
我们首先将所有数据读入 tHashOutput 组件,然后在整个作业期间将数据保存在内存中。 Talend 有时会出于某种奇怪的原因隐藏这些组件,但您可以通过将它们重新添加到项目属性 -> 设计器 -> 调色板设置中来重新启用它们:
接下来,我们使用 tHashInput 组件(链接到前一个 tHashOutput 组件 - 不要忘记将相同的模式添加到 tHashInput 组件)从哈希中读回数据,然后使用 tAggregateRow 组件并通过“构建" 有效地区分建筑价值:
然后我们使用 tFlowToIterate 遍历“building”的不同值,然后通过当前正在迭代的 building 值过滤哈希(第二次读取):
最后,我们再次确保附加到以 building 列中的值命名的文件: