2017-04-14 33 views
2

下面是訂單清單,有沒有辦法找到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   | 

我一定要找到所有誰沒買沒人購買的物品,並創建一個表不包括這些人的人嗎?

+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; 

你可能在想:「這是什麼?」。

子查詢計算每個產品的最小人數和最大人數。如果這些都是一樣的,那麼只有一個人是唯一的購買者。

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)作爲窗口函數。

+0

如果數據庫是mysql,該怎麼辦? – Teja

+1

@Teja。 。 。這個問題被標記爲Postgres。如果你對MySQL有疑問,那就把它當成一個新問題。 –

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 
0

正被接合的聯視圖獲取所有對只有一個爲person_id的product_ids。一旦找到所有的product_ids,它們將被加入到原始客戶表中以獲取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; 
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 
+0

我更喜歡這個解決方案。不知道'bool_and'。 –

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) 

首先是出現在一個訂購產品的標識中找到。然後,我們從所有人(在訂單中)減去那些沒有訂單的人(即所有至少訂購其他人訂購的產品的人)的訂單。

相關問題