我有一堆聚合的事件表(order 是其中之一),我可以像这样查询
SELECT * FROM events WHERE aggregate_id = :order_id AND aggregate_type = :order_type
这适用于简单的情况,但它会更多地涉及 duplicate created 事件。业务需求之一是订单可以重复(从概念上讲,请考虑move
,而不是copy
)。这将关闭原始订单,然后工作人员可以继续处理新订单。为了显示订单的完整历史记录,不仅要显示当前订单的事件,还要显示任何原始订单上的事件。
这是一个简化的例子:
订单 3
订单 2
订单 1
我提出了一个相当简单的查询,适用于这种情况:
WITH RECURSIVE original_orders(order_id) AS (
select aggregate_id
from events
where aggregate_type = 'order'
and aggregate_id = :order_id
and event_name = 'duplicate created'
UNION ALL
select body->'$.duplicatedFromOrderId'
from original_orders
inner join events on (aggregate_type = 'order' and aggregate_id = order_id and event_name = 'duplicate created')
)
SELECT events.*
FROM events
INNER JOIN original_orders ON aggregate_id = order_id;
-- extra context from the real (not simplified) use-case:
-- I actually use the CTE twice, because "notes" are stored separately
-- INNER JOIN users ON event.user_id - to get more info
-- UNION ALL SELECT * FROM notes JOIN original_orders ON order_id = notes.object_id
递归 CTE 最终选择从最新订单(基本情况部分)开始的订单 ID,然后通过从事件正文中获取原始订单 ID 进行递归。
该示例的结果将是具有 3 行的单列 order_id
:(3, 2, 1)
。
问题在于,如果我们查看原始订单(在本例中为订单 1),根本不会显示任何事件,因为它没有重复创建事件。因此,任何不重复的订单在基本情况下都不会选择任何内容,因此 CTE 将返回一个空结果集。
我觉得我的逻辑有些缺陷,而且我缺少[明显]简单的方法来获得我需要的东西。我认为在基本情况下,我可以改为搜索 ANY 事件名称和 GROUP BY id,从而在基本情况查询中获得 order_id
,即使订单不是重复的(以类似的方式我可以使用 SELECT DISTINCT
并放弃 GROUP BY
但它实际上是同一件事)。像这样:
WITH RECURSIVE original_orders(order_id) AS (
select aggregate_id
from events
where aggregate_type = 'order'
and aggregate_id = :order_id
group by aggregate_id
UNION ALL
-- ...
)
这感觉像是一种解决方法,所以我很想修正我的逻辑。我错过了什么?
可重现的例子:
create table events
(
id int auto_increment,
aggregate_type varchar(100) not null,
aggregate_id varchar(255) not null,
event_name varchar(255) not null,
occurred_on datetime not null,
body json not null,
constraint events_pk
primary key (id)
);
insert into events (aggregate_type, aggregate_id, event_name, occurred_on, body)
values ('order', 1, 'created', '2020-05-05 09:00:00', json_object()),
('order', 1, 'closed', '2020-05-06 09:00:00', json_object()),
('order', 2, 'duplicate created', '2020-05-06 09:00:00', json_object('duplicatedFromOrderId', 1)),
('order', 2, 'received', '2020-05-07 09:00:00', json_object()),
('order', 2, 'closed', '2020-05-08 09:00:00', json_object()),
('order', 3, 'duplicate created', '2020-05-08 09:00:00', json_object('duplicatedFromOrderId', 2)),
('order', 3, 'shipped', '2020-05-09 09:00:00', json_object());
使用 :order_id = 3
运行查询应返回所有 7 个事件。
使用 :order_id = 2
运行查询应返回 5 个事件(应忽略订单 3 的事件)。
使用 :order_id = 1
运行查询应返回 2 个事件。
答案 0 :(得分:2)
AND GPA < 3