如何在 mySQL 中从聚合中排除成对的行?

Posted

技术标签:

【中文标题】如何在 mySQL 中从聚合中排除成对的行?【英文标题】:How do I exclude pairs of rows from being aggregated in mySQL? 【发布时间】:2017-03-30 15:07:51 【问题描述】:

我们对操作进行了审计跟踪,并要求我报告这些操作所花费的平均时间。

不幸的是,审计跟踪包含“取消”条目,实质上排除了先前的操作。

所以,一些数据。

AuditTrail
ID OrderID ActionQty ActionDate
1  1        1        2002-02-02
2  2        1        2002-02-02
3  1       -1        2003-03-03
4  1        1        2004-04-04

Orders
OrderID OrderDate
1       2001-01-01
2       2002-02-02

比较的基准日期是不同的 ActionDate。

这是所需的平均值。

在上面的示例中,需要排除 AuditTrail 条目 1 和 3,因为条目 3 是“取消”,因此需要排除先前的非取消条目(条目 1)。 ID 是连续的,但对于一个订单不一定是连续的,因为有许多订单和许多审计跟踪条目。

更复杂的是,我们可以看到“取消”的运行,这需要进一步回滚。

例如

AuditTrail
ID   OrderID ActionQty ActionDate
1030 99       1        2002-02-02
1031 99       1        2002-02-02
1032 99      -1        2003-03-03
1033 99      -1        2004-04-04

在这个例子中,2进2出。

所以。

平均值是总数除以计数。我们可以轻松地使用 SUM(ActionQty) (GROUP'd BY AuditTrail.OrderID) 来获得正确的订单计数。

获取 AuditEntry 的天数也很容易 (TIMESTAMPDIFF(DAY, Orders.OrderDate, AuditTrail.ActionDate))。

但排除正确的...我无法解决。

有什么线索吗?

【问题讨论】:

那么在最后一个例子中,The number of days for an audit entry 在订单 99 上的结果是什么?会不会是0,因为实际上所有审计行都被取消了?我想,另一种提问方式是:“根据您的示例数据,您想要的结果是什么?” 是的。我确实错过了预期/期望的结果。 OrderID 1 将是 3y3m3d(以天为单位)。 OrderID 2 为 0 OrderID 99 为 0 【参考方案1】:

您可以使用行号方法进行匹配。 给定

MariaDB [sandbox]> select * from t;
+------+---------+-----------+------------+
| ID   | OrderID | ActionQty | ActionDate |
+------+---------+-----------+------------+
|    1 |       1 |         1 | 2002-02-02 |
|    2 |       2 |         1 | 2002-02-02 |
|    3 |       1 |        -1 | 2003-03-03 |
|    4 |       1 |         1 | 2004-04-04 |
| 1030 |      99 |         1 | 2002-02-02 |
| 1031 |      99 |         1 | 2002-02-02 |
| 1032 |      99 |        -1 | 2003-03-03 |
| 1033 |      99 |        -1 | 2004-04-04 |
+------+---------+-----------+------------+
8 rows in set (0.00 sec)

这个查询

Select s.id,s.orderid,s.actionqty,s.actiondate
from
(
select t.*, 
        if(t.orderid<>@p ,@rn:=1,@rn:=@rn+1) rn,
        @p:=t.orderid p
from t,(select @block:=0,@rn:=0,@p:=0) rn
where actionqty > 0
order by orderid,id
)s
left join
(
select t.*, 
        if(t.orderid<>@p ,@rn:=1,@rn:=@rn+1) rn,
        @p:=t.orderid p
from t,(select @block:=0,@rn:=0,@p:=0) rn
where actionqty < 0
order by orderid,id
) cans on s.orderid = cans.orderid and s.rn = cans.rn
where cans.id is null

结果

+------+---------+-----------+------------+
| id   | orderid | actionqty | actiondate |
+------+---------+-----------+------------+
|    4 |       1 |         1 | 2004-04-04 |
|    2 |       2 |         1 | 2002-02-02 |
+------+---------+-----------+------------+
2 rows in set (0.00 sec)

【讨论】:

mysql上,所以没有无法重用表t。 :-/ 尝试用你的表名替换 t @RichardAQuadling - 为什么?是临时表吗?因为这是您无法在查询中访问表两次的主要原因。

以上是关于如何在 mySQL 中从聚合中排除成对的行?的主要内容,如果未能解决你的问题,请参考以下文章

C# Regex - 如何从字符串中删除多个成对的括号

如何在一个请求中从 Binance API 获取所有(或多个)对的历史 klines?

如何使用python查找成对的卡片包列表

如何在基于 Spring 的反应式应用程序中从身份验证中排除路径?

1.2 如何找出唯一成对的数(4种解法)

如何在 PySpark 中从表中导入数据时排除 Header