Using EXCEPT with NOT EXISTS
SELECT DISTINCT cname
FROM account AS cust_account
WHERE NOT EXISTS ( SELECT type
FROM account
EXCEPT
SELECT type
FROM account
WHERE account.cname = cust_account.cname )
Can someone please explain step-by-step how the query produces the result required by the question? I am just learning about NOT EXISTS and am not sure what values it takes from the parenthesis and where the WHERE clause belongs with.
This is sample table account
query relational-division
New contributor
add a comment |
SELECT DISTINCT cname
FROM account AS cust_account
WHERE NOT EXISTS ( SELECT type
FROM account
EXCEPT
SELECT type
FROM account
WHERE account.cname = cust_account.cname )
Can someone please explain step-by-step how the query produces the result required by the question? I am just learning about NOT EXISTS and am not sure what values it takes from the parenthesis and where the WHERE clause belongs with.
This is sample table account
query relational-division
New contributor
add a comment |
SELECT DISTINCT cname
FROM account AS cust_account
WHERE NOT EXISTS ( SELECT type
FROM account
EXCEPT
SELECT type
FROM account
WHERE account.cname = cust_account.cname )
Can someone please explain step-by-step how the query produces the result required by the question? I am just learning about NOT EXISTS and am not sure what values it takes from the parenthesis and where the WHERE clause belongs with.
This is sample table account
query relational-division
New contributor
SELECT DISTINCT cname
FROM account AS cust_account
WHERE NOT EXISTS ( SELECT type
FROM account
EXCEPT
SELECT type
FROM account
WHERE account.cname = cust_account.cname )
Can someone please explain step-by-step how the query produces the result required by the question? I am just learning about NOT EXISTS and am not sure what values it takes from the parenthesis and where the WHERE clause belongs with.
This is sample table account
query relational-division
query relational-division
New contributor
New contributor
edited 1 hour ago
Paul White♦
49.1k14260414
49.1k14260414
New contributor
asked 9 hours ago
BhargBharg
11
11
New contributor
New contributor
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
There are three separate parts to the query. I'll label them so I can reference each more clearly:
SELECT DISTINCT cname -- Part A
FROM account AS cust_account
WHERE NOT EXISTS ( SELECT type -- Part B
FROM account
EXCEPT
SELECT type -- Part C
FROM account
WHERE account.cname = cust_account.cname )
First the inner query. Part C lists all type
values for account
rows owned by the customer currently being considered by the outer query (Part A). Conceptually you can think of the DBMS reading all rows that match the outer query then stepping through them one at a time. For each outer row it executes the inner query. (In reality likely something more time-efficient happens but it will be logically equivalent to this.)
Part C is sometimes called a correlated sub-query because it is matched (correlated) with a value coming from the outer query. In this case it is matching on cname
. It is the WHERE clause that tells the DBMS to match Part C to Part A. cust_account
is an alias defined in the outer query. Because a single table - account
- is used three times in the statement the alias allows us to specify exactly which of these three we want to reference. It is the alias which allows us to say "match Part C to Part A."
Part B lists all type
values from table account
. This part has no WHERE so it lists all accounts for all users, not just the one currently being considered by the outer query. This part is not correlated.
The EXCEPT takes the results of the query above it (Part B) and removes those rows which occur in the query below it (Part C). Since Part B is "all types that are in the database" and Part C is "all types the current cname owns" then "B except C" is "all types except those which the current cname owns." If we have a list of all types, and we remove those which the cname owns, what is left is those types which the cname does not own. So if the inner query has any rows (for the current cname) we know there is at least one type of account that cname does not own.
EXISTS() returns true if the inner query has row(s). So NOT EXISTS() returns true if the inner query is empty. As we have just shown, it will be empty if the current cname owns all types of accounts. So the outer query lists all cname
which have all types of account - as requested in the problem.
add a comment |
You have two tables in this
customers(cname)
accounts(cname,type)
I think you want this. You want to SELECT
all cusotmers that have a matching account. It doesn't make sense to negate everything. And it doesn't make sense to say "every type of account." Because types here are values, and
- it doesn't make sense to have a customer with more than one value.
- it the question means any account, it's easier to select on the join condition itself in the exists,
I think it's a bad question.
SELECT cname
FROM customers AS c
WHERE EXISTS (
SELECT 1
FROM accounts AS a
WHERE a.cname = c.cname
);
It also doesn't make sense to use DISTINCT cname
there unless you know that there can be duplicate names AND if there were duplicate names and you used DISTINCT
then you're no longer talking about customers -- just the values of their names in a (unique) set.
I've added the table 'account' now. And the expected answer is 'McBrien P.', 'Poulovassilis A.' as they have both deposit and current account.
– Bharg
8 hours ago
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Bharg is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f226626%2fusing-except-with-not-exists%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
There are three separate parts to the query. I'll label them so I can reference each more clearly:
SELECT DISTINCT cname -- Part A
FROM account AS cust_account
WHERE NOT EXISTS ( SELECT type -- Part B
FROM account
EXCEPT
SELECT type -- Part C
FROM account
WHERE account.cname = cust_account.cname )
First the inner query. Part C lists all type
values for account
rows owned by the customer currently being considered by the outer query (Part A). Conceptually you can think of the DBMS reading all rows that match the outer query then stepping through them one at a time. For each outer row it executes the inner query. (In reality likely something more time-efficient happens but it will be logically equivalent to this.)
Part C is sometimes called a correlated sub-query because it is matched (correlated) with a value coming from the outer query. In this case it is matching on cname
. It is the WHERE clause that tells the DBMS to match Part C to Part A. cust_account
is an alias defined in the outer query. Because a single table - account
- is used three times in the statement the alias allows us to specify exactly which of these three we want to reference. It is the alias which allows us to say "match Part C to Part A."
Part B lists all type
values from table account
. This part has no WHERE so it lists all accounts for all users, not just the one currently being considered by the outer query. This part is not correlated.
The EXCEPT takes the results of the query above it (Part B) and removes those rows which occur in the query below it (Part C). Since Part B is "all types that are in the database" and Part C is "all types the current cname owns" then "B except C" is "all types except those which the current cname owns." If we have a list of all types, and we remove those which the cname owns, what is left is those types which the cname does not own. So if the inner query has any rows (for the current cname) we know there is at least one type of account that cname does not own.
EXISTS() returns true if the inner query has row(s). So NOT EXISTS() returns true if the inner query is empty. As we have just shown, it will be empty if the current cname owns all types of accounts. So the outer query lists all cname
which have all types of account - as requested in the problem.
add a comment |
There are three separate parts to the query. I'll label them so I can reference each more clearly:
SELECT DISTINCT cname -- Part A
FROM account AS cust_account
WHERE NOT EXISTS ( SELECT type -- Part B
FROM account
EXCEPT
SELECT type -- Part C
FROM account
WHERE account.cname = cust_account.cname )
First the inner query. Part C lists all type
values for account
rows owned by the customer currently being considered by the outer query (Part A). Conceptually you can think of the DBMS reading all rows that match the outer query then stepping through them one at a time. For each outer row it executes the inner query. (In reality likely something more time-efficient happens but it will be logically equivalent to this.)
Part C is sometimes called a correlated sub-query because it is matched (correlated) with a value coming from the outer query. In this case it is matching on cname
. It is the WHERE clause that tells the DBMS to match Part C to Part A. cust_account
is an alias defined in the outer query. Because a single table - account
- is used three times in the statement the alias allows us to specify exactly which of these three we want to reference. It is the alias which allows us to say "match Part C to Part A."
Part B lists all type
values from table account
. This part has no WHERE so it lists all accounts for all users, not just the one currently being considered by the outer query. This part is not correlated.
The EXCEPT takes the results of the query above it (Part B) and removes those rows which occur in the query below it (Part C). Since Part B is "all types that are in the database" and Part C is "all types the current cname owns" then "B except C" is "all types except those which the current cname owns." If we have a list of all types, and we remove those which the cname owns, what is left is those types which the cname does not own. So if the inner query has any rows (for the current cname) we know there is at least one type of account that cname does not own.
EXISTS() returns true if the inner query has row(s). So NOT EXISTS() returns true if the inner query is empty. As we have just shown, it will be empty if the current cname owns all types of accounts. So the outer query lists all cname
which have all types of account - as requested in the problem.
add a comment |
There are three separate parts to the query. I'll label them so I can reference each more clearly:
SELECT DISTINCT cname -- Part A
FROM account AS cust_account
WHERE NOT EXISTS ( SELECT type -- Part B
FROM account
EXCEPT
SELECT type -- Part C
FROM account
WHERE account.cname = cust_account.cname )
First the inner query. Part C lists all type
values for account
rows owned by the customer currently being considered by the outer query (Part A). Conceptually you can think of the DBMS reading all rows that match the outer query then stepping through them one at a time. For each outer row it executes the inner query. (In reality likely something more time-efficient happens but it will be logically equivalent to this.)
Part C is sometimes called a correlated sub-query because it is matched (correlated) with a value coming from the outer query. In this case it is matching on cname
. It is the WHERE clause that tells the DBMS to match Part C to Part A. cust_account
is an alias defined in the outer query. Because a single table - account
- is used three times in the statement the alias allows us to specify exactly which of these three we want to reference. It is the alias which allows us to say "match Part C to Part A."
Part B lists all type
values from table account
. This part has no WHERE so it lists all accounts for all users, not just the one currently being considered by the outer query. This part is not correlated.
The EXCEPT takes the results of the query above it (Part B) and removes those rows which occur in the query below it (Part C). Since Part B is "all types that are in the database" and Part C is "all types the current cname owns" then "B except C" is "all types except those which the current cname owns." If we have a list of all types, and we remove those which the cname owns, what is left is those types which the cname does not own. So if the inner query has any rows (for the current cname) we know there is at least one type of account that cname does not own.
EXISTS() returns true if the inner query has row(s). So NOT EXISTS() returns true if the inner query is empty. As we have just shown, it will be empty if the current cname owns all types of accounts. So the outer query lists all cname
which have all types of account - as requested in the problem.
There are three separate parts to the query. I'll label them so I can reference each more clearly:
SELECT DISTINCT cname -- Part A
FROM account AS cust_account
WHERE NOT EXISTS ( SELECT type -- Part B
FROM account
EXCEPT
SELECT type -- Part C
FROM account
WHERE account.cname = cust_account.cname )
First the inner query. Part C lists all type
values for account
rows owned by the customer currently being considered by the outer query (Part A). Conceptually you can think of the DBMS reading all rows that match the outer query then stepping through them one at a time. For each outer row it executes the inner query. (In reality likely something more time-efficient happens but it will be logically equivalent to this.)
Part C is sometimes called a correlated sub-query because it is matched (correlated) with a value coming from the outer query. In this case it is matching on cname
. It is the WHERE clause that tells the DBMS to match Part C to Part A. cust_account
is an alias defined in the outer query. Because a single table - account
- is used three times in the statement the alias allows us to specify exactly which of these three we want to reference. It is the alias which allows us to say "match Part C to Part A."
Part B lists all type
values from table account
. This part has no WHERE so it lists all accounts for all users, not just the one currently being considered by the outer query. This part is not correlated.
The EXCEPT takes the results of the query above it (Part B) and removes those rows which occur in the query below it (Part C). Since Part B is "all types that are in the database" and Part C is "all types the current cname owns" then "B except C" is "all types except those which the current cname owns." If we have a list of all types, and we remove those which the cname owns, what is left is those types which the cname does not own. So if the inner query has any rows (for the current cname) we know there is at least one type of account that cname does not own.
EXISTS() returns true if the inner query has row(s). So NOT EXISTS() returns true if the inner query is empty. As we have just shown, it will be empty if the current cname owns all types of accounts. So the outer query lists all cname
which have all types of account - as requested in the problem.
answered 3 hours ago
Michael GreenMichael Green
14.2k82959
14.2k82959
add a comment |
add a comment |
You have two tables in this
customers(cname)
accounts(cname,type)
I think you want this. You want to SELECT
all cusotmers that have a matching account. It doesn't make sense to negate everything. And it doesn't make sense to say "every type of account." Because types here are values, and
- it doesn't make sense to have a customer with more than one value.
- it the question means any account, it's easier to select on the join condition itself in the exists,
I think it's a bad question.
SELECT cname
FROM customers AS c
WHERE EXISTS (
SELECT 1
FROM accounts AS a
WHERE a.cname = c.cname
);
It also doesn't make sense to use DISTINCT cname
there unless you know that there can be duplicate names AND if there were duplicate names and you used DISTINCT
then you're no longer talking about customers -- just the values of their names in a (unique) set.
I've added the table 'account' now. And the expected answer is 'McBrien P.', 'Poulovassilis A.' as they have both deposit and current account.
– Bharg
8 hours ago
add a comment |
You have two tables in this
customers(cname)
accounts(cname,type)
I think you want this. You want to SELECT
all cusotmers that have a matching account. It doesn't make sense to negate everything. And it doesn't make sense to say "every type of account." Because types here are values, and
- it doesn't make sense to have a customer with more than one value.
- it the question means any account, it's easier to select on the join condition itself in the exists,
I think it's a bad question.
SELECT cname
FROM customers AS c
WHERE EXISTS (
SELECT 1
FROM accounts AS a
WHERE a.cname = c.cname
);
It also doesn't make sense to use DISTINCT cname
there unless you know that there can be duplicate names AND if there were duplicate names and you used DISTINCT
then you're no longer talking about customers -- just the values of their names in a (unique) set.
I've added the table 'account' now. And the expected answer is 'McBrien P.', 'Poulovassilis A.' as they have both deposit and current account.
– Bharg
8 hours ago
add a comment |
You have two tables in this
customers(cname)
accounts(cname,type)
I think you want this. You want to SELECT
all cusotmers that have a matching account. It doesn't make sense to negate everything. And it doesn't make sense to say "every type of account." Because types here are values, and
- it doesn't make sense to have a customer with more than one value.
- it the question means any account, it's easier to select on the join condition itself in the exists,
I think it's a bad question.
SELECT cname
FROM customers AS c
WHERE EXISTS (
SELECT 1
FROM accounts AS a
WHERE a.cname = c.cname
);
It also doesn't make sense to use DISTINCT cname
there unless you know that there can be duplicate names AND if there were duplicate names and you used DISTINCT
then you're no longer talking about customers -- just the values of their names in a (unique) set.
You have two tables in this
customers(cname)
accounts(cname,type)
I think you want this. You want to SELECT
all cusotmers that have a matching account. It doesn't make sense to negate everything. And it doesn't make sense to say "every type of account." Because types here are values, and
- it doesn't make sense to have a customer with more than one value.
- it the question means any account, it's easier to select on the join condition itself in the exists,
I think it's a bad question.
SELECT cname
FROM customers AS c
WHERE EXISTS (
SELECT 1
FROM accounts AS a
WHERE a.cname = c.cname
);
It also doesn't make sense to use DISTINCT cname
there unless you know that there can be duplicate names AND if there were duplicate names and you used DISTINCT
then you're no longer talking about customers -- just the values of their names in a (unique) set.
edited 8 hours ago
answered 8 hours ago
Evan CarrollEvan Carroll
31.1k865206
31.1k865206
I've added the table 'account' now. And the expected answer is 'McBrien P.', 'Poulovassilis A.' as they have both deposit and current account.
– Bharg
8 hours ago
add a comment |
I've added the table 'account' now. And the expected answer is 'McBrien P.', 'Poulovassilis A.' as they have both deposit and current account.
– Bharg
8 hours ago
I've added the table 'account' now. And the expected answer is 'McBrien P.', 'Poulovassilis A.' as they have both deposit and current account.
– Bharg
8 hours ago
I've added the table 'account' now. And the expected answer is 'McBrien P.', 'Poulovassilis A.' as they have both deposit and current account.
– Bharg
8 hours ago
add a comment |
Bharg is a new contributor. Be nice, and check out our Code of Conduct.
Bharg is a new contributor. Be nice, and check out our Code of Conduct.
Bharg is a new contributor. Be nice, and check out our Code of Conduct.
Bharg is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f226626%2fusing-except-with-not-exists%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown