在我们的项目中,我们必须根据收到的输入数据定期计算聚合和进一步的计算。
一个常见的要求是计算输入数据流中某些行之间的时差。
例如,这是我的输入数据流:
时间戳事件值
2017-05-21 11:33 e1 17
2017-05-21 11:37 e2 18
2017-05-21 11:38 e3 18
2017-05-21 11:39 e1 19
2017-05-21 11:42 e2 19
我现在想要计算e2事件和最后收到的e1事件之间的所有时间跨度(按时间戳排序)。
我希望结果如下: 3分钟) 4分钟(分钟)
类似的要求是计算相同类型事件之间的时间跨度(即e1事件之间的所有差异),我期望这个结果: 6分钟(分钟)
到目前为止我的尝试:
使用LAG函数和WHEN子句可以很容易地实现这种分析,但遗憾的是U-SQL中缺少WHEN子句。 如果它是T-SQL,也可以使用语句的SELECT-Clause中的Sub-Selects来解决这个问题,但不幸的是,这在U-SQL中也是不可能的。
您对如何解决此问题有任何建议或示例脚本吗? 非常感谢你的帮助!
答案 0 :(得分:1)
在U-SQL中,您可以使用c#方法进行简单的日期算术。如果您的数据与您描述的一样简单,您可以只对e1和e2事件进行排名然后加入它们,如下所示:
@data =
EXTRACT Timestamp DateTime,
Event string,
Value int
FROM "/input/input58.csv"
USING Extractors.Csv();
//@data = SELECT *
// FROM (
// VALUES
// ( "2017-05-21 11:33", "e1", 17 ),
// ( "2017-05-21 11:37", "e2", 18 ),
// ( "2017-05-21 11:38", "e3", 18 ),
// ( "2017-05-21 11:39", "e1", 19 ),
// ( "2017-05-21 11:42", "e2", 19 )
// ) AS T(Timestamp, Event, Value);
@e1 =
SELECT ROW_NUMBER() OVER(ORDER BY Timestamp) AS rn,
*
FROM @data
WHERE Event == "e1";
@e2 =
SELECT ROW_NUMBER() OVER(ORDER BY Timestamp) AS rn,
*
FROM @data
WHERE Event == "e2";
@working =
SELECT
(e2.Timestamp - e1.Timestamp).TotalSeconds AS diff_sec,
(e2.Timestamp - e1.Timestamp).ToString() AS diff_hhmmss,
e1.Timestamp AS ts1,
e2.Timestamp AS ts2
FROM @e1 AS e1
INNER JOIN @e2 AS e2 ON e1.rn == e2.rn;
OUTPUT @working TO "/output/output.csv"
USING Outputters.Csv(quoting:false);
我的结果,显示样本数据的4分钟和3分钟:
这对你有用吗?如果没有,请提供更实际的数据样本。
答案 1 :(得分:1)
@data =
SELECT
LAST_VALUE(Event == "e1" ? Timestamp : (DateTime?)null) OVER (ORDER BY Timestamp) AS E1Time
// MAX(Event == "e1" ? Timestamp : DateTime.MinValue) OVER (ORDER BY Timestamp) AS E1Time
, Timestamp AS E2Time
FROM @events
HAVING Event == "e2"
;
因为聚合/ WF 忽略 null(至少他们应该,LAST_VALUE的U-SQL文档没有说明,所以需要验证)。这允许模拟条件行为,例如WHEN。使用MAX / MIN和适当的默认值可以获得类似的行为。
也就是说,您应该详细说明输入数据和预期结果,这可能会改变解决方案。也就是说,如果出现异常数据序列并且预期会出现什么行为(或者为了简单起见至少可以容忍):
等。在某些复杂的情况下,你可能不得不通过REDUCE ALL推迟自定义减速器(这是最后的手段!),但这会限制可以处理的数据的大小。