There are several questions that are close to this, but I haven't found that they address my situation. I have the following table, SUBSCRIPTIONS, that identifies individual amenities in a subscriber's subscription:
User Id | Category | Rank | Method | Start Date | End Date | Amenity |
---|---|---|---|---|---|---|
A001 | A | B | C | 01-JUN-23 | 01-JUN-24 | A1 |
A001 | A | B | C | 01-JUN-23 | 01-JUN-24 | A2 |
A002 | A | B | C | 15-OCT-23 | 15-OCT-24 | A1 |
A002 | A | B | C | 15-OCT-23 | 15-OCT-24 | A2 |
A002 | A | B | C | 15-OCT-23 | 15-OCT-24 | A3 |
A003 | D | E | F | 11-NOV-23 | 11-NOV-24 | A1 |
User Id is the subscriber. The combination of Category, Rank, and Method are the way the subscriber signed up for their subscription. The start date is when the subscription starts. The end date is when the subscription ends. Amenity is the individual amenity.
Unfortunately, the subscription isn't identified by a solitary serial number/ID. An individual user's subscription is the combination of User Id, Category, Rank, Method, Start Date, and End Date.
I need to identify distinct User Ids where their subscription of Category = A, Rank = B, and Method = C does not include amenity A3.
So from the above table, I would need to identify that User Id A001 had a subscription combination of A, B, and C but did not have amenity 'A3'. User Id A003 did not have 'A3' but their subscription combination was D, E, and F.
select DISTINCT User Id
from SUBSCRIPTIONS
where Category = 'A'
and Rank = 'B'
and Method = 'C'
and Amenity <> 'A3'
This is clearly wrong because it's just removing rows that have amenity 'A3'. I researched GROUPING SETS
and GROUP BY CUBE
, but I'm not aggregating data here so grouping expressions aren't working.
What is the proper approach for creating sets and checking for a specified value in each set?
The desired result based on the sample data above would be...
User Id |
---|
A001 |
...as that is the only User Id with amenity A3 on a combination of A, B, and C.
Use GROUP BY
and conditional aggregation in a HAVING
clause:
SELECT User_Id
FROM SUBSCRIPTIONS
WHERE Category = 'A'
AND Rank = 'B'
AND Method = 'C'
GROUP BY user_id
HAVING COUNT(CASE Amenity WHEN 'A3' THEN 1 END) = 0;
Which, for the sample data:
CREATE TABLE subscriptions (User_Id, Category, Rank, Method, Start_Date, End_Date, Amenity) AS
SELECT 'A001', 'A', 'B', 'C', DATE '2023-06-01', DATE '2024-06-01', 'A1' FROM DUAL UNION ALL
SELECT 'A001', 'A', 'B', 'C', DATE '2023-06-01', DATE '2024-06-01', 'A2' FROM DUAL UNION ALL
SELECT 'A002', 'A', 'B', 'C', DATE '2023-10-15', DATE '2024-10-15', 'A1' FROM DUAL UNION ALL
SELECT 'A002', 'A', 'B', 'C', DATE '2023-10-15', DATE '2024-10-15', 'A2' FROM DUAL UNION ALL
SELECT 'A002', 'A', 'B', 'C', DATE '2023-10-15', DATE '2024-10-15', 'A3' FROM DUAL UNION ALL
SELECT 'A003', 'D', 'E', 'F', DATE '2023-11-11', DATE '2024-11-11', 'A1' FROM DUAL;
Outputs:
USER_ID |
---|
A001 |