Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Customers that purchased every item

I’m trying to construct a query that will show me a list of customers that purchased all items.

I’m thinking perhaps the distinct and EXISTS option or perhaps a count() may be a solution but I’m unsure how to put this all together. Any help would be greatly appreciated.

Below is my sample data and expected output.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


CREATE TABLE customers (CUSTOMER_ID, FIRST_NAME, LAST_NAME) AS 
SELECT 1, 'Abby', 'Katz' FROM DUAL UNION ALL
SELECT 2, 'Lisa', 'Jones' FROM DUAL UNION ALL 
SELECT 3, 'Joanne','Dalton' FROM DUAL; 

CREATE TABLE items (PRODUCT_ID, PRODUCT_NAME) AS 
SELECT 100, 'Black Shoes' FROM DUAL UNION ALL
 SELECT 101, 'Brown Shoes' FROM DUAL UNION ALL
SELECT 102, 'White Shoes' FROM DUAL; 

CREATE TABLE purchases (CUSTOMER_ID, PRODUCT_ID, QUANTITY, PURCHASE_DATE) AS
SELECT 1, 100, 1, TIMESTAMP'2024-05-11 09:54:48' FROM DUAL UNION ALL
SELECT 1, 101, 1, TIMESTAMP'2024-05-11 19:54:48' FROM DUAL UNION ALL
SELECT 1, 102, 1, TIMESTAMP'2024-06-09 14:54:48' FROM DUAL UNION ALL
SELECT 3, 100, 1, TIMESTAMP'2024-06-09 11:34:44' FROM DUAL UNION ALL
SELECT 3,102,1, TIMESTAMP '2024-05-10 19:04:18' FROM DUAL;

CUSTOMER_ID FIRST_NAME LAST_NAME DISTINCT_ITEM_CNT

1 Abby Katz 3

>Solution :

You can use a PARTITIONed OUTER JOIN to generate the count:

SELECT c.*,
       p.distinct_item_cnt
FROM   customers c
       INNER JOIN (
         SELECT customer_id,
                COUNT(DISTINCT p.product_id) AS distinct_item_cnt
         FROM   items i
                LEFT OUTER JOIN purchases p
                PARTITION BY (p.customer_id)
                ON (p.product_id  = i.product_id)
         GROUP BY p.customer_id
         HAVING COUNT(DISTINCT p.product_id) = COUNT(i.product_id)
       ) p
       ON p.customer_id = c.customer_id

Which, for the sample data, outputs:

CUSTOMER_ID FIRST_NAME LAST_NAME DISTINCT_ITEM_CNT
1 Abby Katz 3

If you do not want the final DISTINCT_ITEM_CNT column then you can find the customers using NOT EXISTS:

SELECT *
FROM   customers c
WHERE  NOT EXISTS(
         SELECT 1
         FROM   items i
                LEFT OUTER JOIN purchases p
                ON (   p.product_id  = i.product_id
                   AND p.customer_id = c.customer_id)
         WHERE  p.customer_id IS NULL
       )

fiddle

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading