Reputation: 402
I have the following two tables
Table: Customer
Cust_ID FName
------- -----
1 X
2 Y
3 Z
Table: Account
Acct_Number Cust_ID Acct_Type
----------- ------- ---------
1001 1 savings
1002 1 capital
1003 2 savings
1004 2 capital
1005 2 vip
1006 3 capital
1007 3 vip
There are three different types of account in Account table, (savings, capital and vip), I want to find the customer who have an account of every type which is listed in Account relation(without using any aggregate operator).That is, in this case, Y will qualify, as he is the only one who has all types of account.
I got a suggestion to try the following, which is not working:
SELECT c.FName, c.Cust_ID FROM Customer AS c
JOIN Account AS a1 ON c.Cust_ID = a1.Cust_ID
JOIN Account AS a2 ON c.Cust_ID = a2.Cust_ID
WHERE a1.Acct_Type <> a2.Acct_Type;
The above query is giving the customer who has account in two distinct type, not all. Helps are highly appreciated.
Upvotes: 1
Views: 97
Reputation: 7171
What you want is relational division:
forall x:p(x)
but this is not possible to express in sql so you have to rewrite it to:
not exists x : not p(x)
in other words, for which customers does it not exists an accounttype such that the account does not have it. Something like:
SELECT c.FName, c.Cust_ID
FROM Customer AS c
WHERE NOT EXISTS (
select distinct Acct_Type
from Account t
where not exists (
select 1 from Account as a
where a.cust_id = c.cust_id
and a.Acct_Type = t. Acct_Type
)
);
Edit: did not notice that aggregates was disallowed
Upvotes: 2
Reputation: 5669
EDIT: If the Acct_Type
values are not previously known, the following query can be used to get the desired results. Obviously, it is much more tedious than using aggregation operations.
SELECT c.*
FROM Customer AS c
INNER JOIN
(
SELECT DISTINCT
all_combinations.Cust_ID
FROM Account Acct
RIGHT JOIN
(
SELECT
c.Cust_ID,
a.Acct_Type
FROM Customer AS c
CROSS JOIN
(SELECT DISTINCT Acct_Type FROM Account) AS a
) all_combinations
ON Acct.Cust_ID = all_combinations.Cust_ID AND Acct.Acct_Type = all_combinations.Acct_Type
WHERE Acct.Cust_ID IS NOT NULL
) all_acct_types
ON c.Cust_ID = all_acct_types.Cust_ID;
Upvotes: 0
Reputation: 32402
here's a query using not exists
select c.* from customer c
where not exists (
select acct_type from account a2
where acct_type not in (
select distinct acct_type
from account a3 where a3.Cust_ID = c.Cust_ID
)
)
Upvotes: 2