Skip to main content
added 189 characters in body
Source Link
ypercubeᵀᴹ
  • 100k
  • 13
  • 217
  • 306

You could rewrite with OR and two EXISTS subqueries and compare performance with your query:

SELECT a.* FROM a WHERE EXISTS ( SELECT FROM b WHERE a.type_id = b.id AND b.user_id = 123 AND a.type = 'dog' ) OR EXISTS ( SELECT FROM c WHERE a.type_id = c.type_id AND c.user_id = 123 AND a.type = 'cat' ) ; 

or:

SELECT a.* FROM a WHERE a.type = 'dog' AND EXISTS ( SELECT FROM b WHERE a.type_id = b.id AND b.user_id = 123 ) OR a.type = 'cat' AND EXISTS ( SELECT FROM c WHERE a.type_id = c.type_id AND c.user_id = 123 ) ; 

Your query seems correct, assuming that there are unique constraints or indexes on b (user_id, id) or on b (id) - and c (user_id, type_id).

It does however looks somewhat obfuscated - it is not clear without careful reading that it restricts the result to rows that have WHERE a.type_id IN ('dog', 'cat').

You could rewrite with OR and two EXISTS subqueries:

SELECT a.* FROM a WHERE EXISTS ( SELECT FROM b WHERE a.type_id = b.id AND b.user_id = 123 AND a.type = 'dog' ) OR EXISTS ( SELECT FROM c WHERE a.type_id = c.type_id AND c.user_id = 123 AND a.type = 'cat' ) ; 

or:

SELECT a.* FROM a WHERE a.type = 'dog' AND EXISTS ( SELECT FROM b WHERE a.type_id = b.id AND b.user_id = 123 ) OR a.type = 'cat' AND EXISTS ( SELECT FROM c WHERE a.type_id = c.type_id AND c.user_id = 123 ) ; 

You could rewrite with OR and two EXISTS subqueries and compare performance with your query:

SELECT a.* FROM a WHERE EXISTS ( SELECT FROM b WHERE a.type_id = b.id AND b.user_id = 123 AND a.type = 'dog' ) OR EXISTS ( SELECT FROM c WHERE a.type_id = c.type_id AND c.user_id = 123 AND a.type = 'cat' ) ; 

or:

SELECT a.* FROM a WHERE a.type = 'dog' AND EXISTS ( SELECT FROM b WHERE a.type_id = b.id AND b.user_id = 123 ) OR a.type = 'cat' AND EXISTS ( SELECT FROM c WHERE a.type_id = c.type_id AND c.user_id = 123 ) ; 

Your query seems correct, assuming that there are unique constraints or indexes on b (user_id, id) or on b (id) - and c (user_id, type_id).

It does however looks somewhat obfuscated - it is not clear without careful reading that it restricts the result to rows that have WHERE a.type_id IN ('dog', 'cat').

Source Link
ypercubeᵀᴹ
  • 100k
  • 13
  • 217
  • 306

You could rewrite with OR and two EXISTS subqueries:

SELECT a.* FROM a WHERE EXISTS ( SELECT FROM b WHERE a.type_id = b.id AND b.user_id = 123 AND a.type = 'dog' ) OR EXISTS ( SELECT FROM c WHERE a.type_id = c.type_id AND c.user_id = 123 AND a.type = 'cat' ) ; 

or:

SELECT a.* FROM a WHERE a.type = 'dog' AND EXISTS ( SELECT FROM b WHERE a.type_id = b.id AND b.user_id = 123 ) OR a.type = 'cat' AND EXISTS ( SELECT FROM c WHERE a.type_id = c.type_id AND c.user_id = 123 ) ;