[英]Matching array of rows with multiple conditions
我有带有以下列的表事务和事务操作。 transactionaction 中的 transactionid 是事务的外键。
事务ID | 姓名 |
---|---|
1 | 跨 1 |
2 | 反式 2 |
3 | 反式 3 |
4 | 反式 4 |
动作ID | 事务ID | 动作类型 | 价值 |
---|---|---|---|
1 | 1 | 1 | 空值 |
2 | 1 | 2 | 空值 |
3 | 1 | 3 | 空值 |
4 | 2 | 1 | 1 |
5 | 2 | 2 | 空值 |
6 | 2 | 3 | 空值 |
我需要找到包含用户传递的所有操作的每个事务。 需要注意的是,某些操作只能根据 actionType(操作 2、3)进行过滤,有些还可以根据值(操作 1)进行过滤。 因此,如果用户想要找到具有操作 2,3 的交易,他应该获得交易 1 和 2。对于这种情况,在此答案https://stackoverflow.com/a/41140629/12035106 的帮助下,我创建了此查询。
SELECT * from transaction
WHERE transactionid in (
SELECT transactionid
FROM public.transactionaction
group by transactionid
having array_agg(actiontype) @> array[2,3]
)
但是,操作 1 需要考虑值,因为 value == null 的操作 1 与 value != null 的操作不同。 在这种情况下,我无法真正使用先前的查询。 我想出了这个查询。
SELECT * from transaction
WHERE transactionid in (
SELECT transactionid
FROM public.transactionaction
group by transactionid
having array_agg(actiontype) @> array[2,3]
) AND transactionid in (
SELECT transactionid
FROM public.transactionaction
WHERE actiontype = 1 AND value is not null
)
这一项工作,因此,我只会得到事务 2,但我觉得我过于复杂了,因为这个查询多次循环遍历同一个表。 我在 actiontype 上创建了一个索引,所以查询计划看起来更好,但也许有更简单的方法来实现相同的结果?
作为一种选择,在 Where 子句中移动操作 (1) 的条件将是一种优雅的选择,因此这种方法消除了任何子查询。
Select Transaction.transactionid, Max(Transaction.name)
From Transaction Inner Join Transactionaction On (Transaction.transactionid=Transactionaction.transactionid)
Where (actiontype=1 And value Is Not Null) Or actiontype<>1
Group by Transaction.transactionid
Having array_agg(actiontype Order by actiontype) = array[1,2,3]
我认为您有一个初始设计问题,即使如此,我也会尽力帮助您进行查询。
您可以使用子查询并了解事务是否具有不同于 null 的 actionType 1(通过聚合函数和“over”以避免“group by”),这样您就知道可以过滤 actionType 2 和3
drop table if exists transaction;
create temp table transaction(
transactionId bigint,
name varchar
) on commit drop;
insert into transaction(transactionId, name) values(1, 'Trans 1');
insert into transaction(transactionId, name) values(2, 'Trans 2');
drop table if exists transactionAction;
create temp table transactionAction(
actionId bigint,
transactionId bigint,
actionType bigint,
value bigint
) on commit drop;
insert into transactionAction(actionId, transactionId, actionType, value) values(1, 1, 1, null);
insert into transactionAction(actionId, transactionId, actionType, value) values(2, 1, 2, null);
insert into transactionAction(actionId, transactionId, actionType, value) values(3, 1, 3, null);
insert into transactionAction(actionId, transactionId, actionType, value) values(4, 2, 1, 1);
insert into transactionAction(actionId, transactionId, actionType, value) values(5, 2, 2, null);
insert into transactionAction(actionId, transactionId, actionType, value) values(6, 2, 3, null);
select
distinct
t.*
from
(
select
ta.actionid,
ta.transactionId,
ta.actionType,
ta.value,
/*sum only if action type 1 is different from null*/
sum(case when ta.actionType = 1 and not ta.value is null then 1 else 0 end) over(partition by ta.transactionId) haveActionOne
from
transactionAction ta
) a
inner join transaction t
on a.transactionId = t.transactionId
where
/*indicates if the transaction in its actions has type 1 different from null in its value*/
a.haveActionOne = 1
and a.actionType in (2,3);
问候,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.