I'm debugging the following SQL statement, trying to understand how it's behaving.
I'm surprised to find that if I change the NOT EXISTS
to just EXISTS
(and querying against the same, unchanged data), I get the exact same output (which is a count of the rows, e.g., 237
). How can this be?
I expected that changing the NOT EXISTS
to just EXISTS
would change it from returning a positive number of rows (e.g., 237
) to returning 0
.
SELECT count(*) FROM blog_tags
WHERE blog_tags.subscribed = true
AND blog_tags.special = true
AND EXISTS (
SELECT 1
FROM tags
INNER JOIN blog_tags AS bt ON bt.tag_id = tags.id
INNER JOIN blogs ON bt.blog_id = blogs.id
WHERE blogs.org_id = 22
AND NOT EXISTS ( /* Removing the "NOT" on this line has no effect */
SELECT 1
FROM blog_tags
INNER JOIN tags AS tg ON blog_tags.tag_id = tg.id
INNER JOIN blogs AS t ON blog_tags.blog_id = t.id
WHERE t.org_id = 4
AND t.active = true
AND t.type = 'foo'
AND t.priority_id = blogs.priority_id
AND tg.name = tags.name
)
);
I'm wondering if I'm conceptually understanding this incorrectly. Re-writing it as psuedo-code:
/* select_1 */
SELECT count(*) FROM sometable_1
WHERE condition_1a
AND condition_1b
AND EXISTS (
/* condition_1c (the entire EXISTS inside these parentheses) */
/* select_2 */
SELECT 1
FROM sometable2
INNER JOIN join_expression_1a
INNER JOIN join_expression_1b
WHERE condition_2a
AND NOT EXISTS ( /* Removing the "NOT" on this line has no effect */
/* condition_2b (the entire NOT EXISTS inside these parentheses */
/* select_3 */
SELECT 1
FROM sometable1
INNER JOIN join_expression_2a
INNER JOIN join_expression_2b
WHERE condition_3a
AND condition_3b
AND condition_3c
AND condition_3d
AND condition_3e
)
);
Following are my interpretations of the above psuedo-code. Are these interpretations true?
count(*)
can only return a non-zero number of rows if(condition_1a AND condition_1b AND condition_1c)
areTrue
condition_1c
is only True if(condition_2a=True AND condition_2b=False)
- if the entire expression returns a non-zero number of rows, then
condition_2b
must beFalse
in order for theNOT EXISTS
to beTrue
. - if the entire expression returns a non-zero number of rows, then changing
NOT EXISTS
toEXISTS
should cause the entire expression to return0
.
I'm using PostgreSQL v9.2.8