Select 行包含一定范围的值但排除了其他列的值

Select rows that contain a range of values while excluding values from other columns

这里的查询碰壁了。尝试查看交易是否包含类型 01,同时排除包含项目 23 或 25 的交易。

这是一个代表。

在SQLfiddle

create table purchases (
  transaction_id int,
  item int,
  type int,
  customer char(1)
  
);

insert into purchases values (1, 23, 01, "A");
insert into purchases values (1, 25, 01, "A");
insert into purchases values (2, 23, 01, "B");
insert into purchases values (2, 25, 01, "B");
insert into purchases values (2, 1, 01, "B");
insert into purchases values (3, 3, 01, "A");
insert into purchases values (4, 23, 01,"B");
insert into purchases values (4, 25, 01,"B");
insert into purchases values (5, 23, 01,"A");
insert into purchases values (6, 4, 02,"C");
insert into purchases values (7, 9, 03,"C");

这是用于识别只有项目 23 和 25 而没有其他任何交易的查询,它有效(应该是交易,1,4 和 5)。

select transaction_id from purchases where item in (23,25)
and transaction_id not in (select transaction_id from purchases where item not in (23,25));

但是,当我努力挑选出类型为 01 而不是项目 23 和 25 的交易时。

我试过了,但它给出了事务 2 和 3,而它应该只有 3,因为 2 确实包含项目 23 和 25。

这是我要进行的查询,基于第一个查询。

select * from purchases where type = 1 and transaction_id not in (select transaction_id from purchases where item in (23,25)
and transaction_id not in (select transaction_id from purchases where item not in (23,25)));

预期结果

transaction_id  item    type    customer
      3          3       01        A
                       

您希望每笔交易一行,因此汇总并 GROUP BY transaction_id。然后有条件地使用HAVING子句和COUNT

select transaction_id
from purchases
group by transaction_id
having count(*) filter (where item = 23) = 0
   and count(*) filter (where item = 25) = 0
   and count(*) filter (where type = 1) > 0
order by transaction_id;

演示:https://dbfiddle.uk/?rdbms=postgres_14&fiddle=520755370f13d41ba35ca12e7eb5277e

如果您想显示与上述交易 ID 匹配的所有行:

select * from purchases where transaction_id in ( <above query> );

这是一种选择

select p.*
from purchases p
join (
       select transaction_id
       from purchases
       group by transaction_id 
       having count(case when item in (25,23) then 1 end)=0
       and    count(case typ when 1 then 1 end)>0
      )x 
on p.transaction_id=x.transaction_id

对于您的示例数据:

insert into purchases values (1, 23, 01, 'A');
insert into purchases values (1, 25, 01, 'A');
insert into purchases values (2, 23, 01, 'B');
insert into purchases values (2, 25, 01, 'B');
insert into purchases values (2, 1, 01, 'B');
insert into purchases values (3, 3, 01, 'A');
insert into purchases values (4, 23, 01,'B');
insert into purchases values (4, 25, 01,'B');
insert into purchases values (5, 23, 01,'A');
insert into purchases values (6, 4, 02,'C');
insert into purchases values (7, 9, 03,'C');

结果:

3   3   1   A

根据您更新后的问题,我建议您使用如下所示的 NOT EXISTS 子句

select * from purchases p1 where not exists
(
select 1 from purchases p2 where p1.transaction_id=p2.transaction_id 
and p2.item in (23,25))
and type=1

fiddle demo link

我看到你已经多次更改了问题中的预期结果(而查询本身并没有改变),所以我不确定你到底想得到什么。 在任何情况下,您都可以使用 this dbfiddle 示例,并使用按不同排序元素过滤的数组: