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
我看到你已经多次更改了问题中的预期结果(而查询本身并没有改变),所以我不确定你到底想得到什么。
在任何情况下,您都可以使用 this dbfiddle 示例,并使用按不同排序元素过滤的数组:
这里的查询碰壁了。尝试查看交易是否包含类型 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
我看到你已经多次更改了问题中的预期结果(而查询本身并没有改变),所以我不确定你到底想得到什么。
在任何情况下,您都可以使用 this dbfiddle 示例,并使用按不同排序元素过滤的数组: