sql—选择只订购特定会议而不订购其他会议的客户机

brccelvz  于 2021-07-24  发布在  Java
关注(0)|答案(3)|浏览(316)

假设我们有一个client表和一个order表,它们是这样链接在一起的:client.id=order.client\u id.order表条目包含一个已购买的产品id。产品表条目包含购买此产品的会议id。
如何选择仅从特定会议列表中购买产品的客户?
我可以用一个php脚本来解决这个问题,发出多个请求,重新排列数据,但这一点都不好玩。
我已经试过了:

select
    o.client_id,
    array_agg(p.conference_id) as conference_ids
from product as p
left join order as o
    on o.id = p.order_id
where
    p.conference_id = any('{ 46545, 46543 }'::int[])

但这并没有起作用,因为它选择的客户不仅从这些会议上购买,而且也从其他会议上购买。
edit:修复了语法正确的sql

yc0p9oo0

yc0p9oo01#

不使用数组的一种方法是:

select client.id
from product as p
left join order as o on o.id = p.order_id
group by client.id
having count(*) filter(where p.conference_id not in (46545, 46543)) = 0;

如果您还想Assert上述两个会议都参加了(即,两个会议都参加了,但没有其他会议),您可以向 HAVING 条款:

select client.id
from product as p
left join order as o on o.id = p.order_id
group by client.id
having count(*) filter(where p.conference_id not in (46545, 46543)) = 0 and
       min(p.conference_id) <> max(p.conference_id);
wpcxdonn

wpcxdonn2#

您可以使用聚合,并使用 having 条款。
查询引用表 client ,您没有选择-这是语法错误。你可以得到 client_id 而是直接从orders表。

select o.client_id, array_agg(p.conference_id) as conference_ids
from orders as o 
inner join product as p on p.product_id = o.id
group by o.client_id
having count(*) filter(where not p.conference_id = any('{ 46545, 46543 }'::int[])) = 0

请注意 order 是语言关键字,因此表名选择不当;我把它改名为 orders 相反。
如果要确保客户端为数组中列出的所有会议下订单,可以向 having 条款;您可以使其独立于具有 array_length() :

having 
    count(distinct p.conference_id) 
        filter(where p.conference_id = any('{ 46545, 46543 }'::int[])) = array_length('{ 46545, 46543 }'::int[], 1)
    and count(*) filter(where not p.conference_id = any('{ 46545, 46543 }'::int[])) = 0
u91tlkcl

u91tlkcl3#

大概你有一张客户表。一个有趣的方法是使用set操作:

select c.id
from clients c
except
select o.client_id
from orders o join
     products p
     on o.id = p.order_id
where p.conference_id not in (46545, 46543);

实际上,我更喜欢聚合方法——它们更通用。但是你问题中的疑问在语法上是不正确的,我觉得你想用 clients table。

相关问题