繁体   English   中英

匹配具有多个条件的行数组

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM