找到只购买没有其他人购买的商品的顾客

时间:2017-04-14 18:52:43

标签: sql postgresql

以下是订单列表,有没有办法找到person_id客户,购买的产品没有其他人购买?

CREATE TABLE orders
AS
  SELECT product_id, person_id
  FROM ( VALUES
    ( 1 , 1 ),
    ( 2 , 1 ),
    ( 2 , 2 ),
    ( 3 , 3 ),
    ( 12, 6 ),
    ( 10, 3 )
  ) AS t(product_id, person_id);

结果如下表所示:

| person_id |
|-----------|
| 3         |
| 6         |

我是否必须找到所有买过没有其他人买过的物品的人,并创建一个不包括那些人的桌子?

5 个答案:

答案 0 :(得分:2)

您希望此人购买的所有产品都是唯一的。

select person_id
from (select t.*,
             min(person_id) over (partition by product_id) as minp,
             max(person_id) over (partition by product_id) as maxp
      from t
     ) t
group by person_id
having sum(case when minp <> maxp then 1 else 0 end) = 0;

你可能在想&#34;嗯?这是做什么的?&#34;。

子查询计算每个产品的最小人数和最大人数。如果这些是相同的,那么一个人是唯一的购买者。

having然后检查某个人没有非单一购买者产品。

也许更直观的逻辑措辞是:

select person_id
from (select t.*,
             count(distinct person_id) over (partition by product_id) as numpersons     
      from t
     ) t
group by person_id
having max(numperson) = 1;

唉,Postgres并不支持COUNT(DISTINCT)作为窗口功能。

答案 1 :(得分:2)

传统的自我联接与布尔聚合

select o0.person_id
from
    orders o0
    left join
    orders o1 on o0.product_id = o1.product_id and o0.person_id <> o1.person_id
group by o0.person_id
having bool_and(o1.product_id is null)
;
 person_id 
-----------
         3
         6

答案 2 :(得分:0)

这是Gordon仅使用聚合的逻辑:

SELECT person_id
FROM
   (
      SELECT product_id,
              -- if count = 1 it's the only customer who bought this product
             min(person_id) as person_id,
             -- if the combination(person_id,product_id) is unique DISTINCT can be removed
             count(distinct person_id) as cnt
      FROM customers
      GROUP BY product_id
    ) AS dt
GROUP BY person_id
HAVING max(cnt) = 1 -- only unique products

答案 3 :(得分:0)

正在连接的内联视图获取只有一个person_id的所有product_id。找到所有product_id后,它们将加入原始customers表以获取person_ids。这应该可以解决你的问题!!

SELECT person_id
  FROM customers c1
INNER JOIN 
       (
          SELECT product_id
            FROM customers
          GROUP BY product_id
          HAVING COUNT(person_id ) = 1
        ) c2
    ON c1.product_id = c2.product_id;

答案 4 :(得分:0)

这是另一种解决方案:

with unique_products as
  (select product_id
   from orders
   group by product_id
   having count(*) = 1)
select person_id
from orders
  except
select person_id
from orders
where not exists 
       (select * from unique_products where unique_products.product_id = orders.product_id)

首先找到单个订单中出现的所有产品标识符。然后我们从所有人(在订单中)减去没有订单的产品(即所有至少订购了其他人订购的产品的人)。