Question

I'm writing a query to determine if a record exists in the db according to some conditions met in other tables.

Now I came up with a situation where I need to know what is the best approach:

either OR the subqueries:

SELECT * from table as tbl WHERE
Exists
(SELECT 1 FROM t1 WHERE t1.id = tbl.id)
OR Exists
(SELECT 1 FROM t2 WHERE t2.col2 = tbl.col2)
OR Exists
(SELECT 1 FROM t3 WHERE t3.othercol = tbl.somecol)

or Use UNION without ORs:

SELECT * from tbl WHERE
Exists
(SELECT 1 FROM t1 WHERE t1.id = tbl.id
 UNION
 SELECT 1 FROM t2 WHERE t2.col2 = tbl.col2)
 UNION
 SELECT 1 FROM t3 WHERE t3.othercol = tbl.somecol)

I need this to be the best in performance, thus the question. Some fields/columns might not be indexed and this might happen in a set of different columns not just 3, maybe even more than 1 per subquery/table.

For best resolution I'm going to publish some complex examples here: How would this be with joins?

SELECT * from table as cli WHERE
Exists 
        (

        SELECT 
            1
        from 
            tbl_import_line_reference as l,
            tbl_import_doc as d
        WHERE
            d.import_key = l.import_key AND
            CAST(Left(d.doc_date,8) as  DATE) BETWEEN  LAST_DAY(NOW() - INTERVAL 6 MONTH) + INTERVAL 1 day AND  NOW()
        AND
            l.prod_ref like '---fmidref%'
        AND
            d.doc_type ='F'
        AND 
            d.car_miposreg_ext_id = cli.car_miposreg_ext_id
        )

    OR
    Exists
        (

        select 
            1
        from 
            tbl_import_line_reference as l,
            tbl_import_doc as d
        WHERE
            d.import_key = l.import_key AND
            CAST(Left(d.doc_date,8) as  DATE) BETWEEN  @data_final + INTERVAL 1 day AND  NOW()
        AND
            l.prod_ref not RLIKE '---fmidneo|---fmidevo'
        AND
            l.act_code = 5
        AND
            l.act_subcode = "7"
        AND
            d.doc_type ='F'
        AND 
            d.car_miposreg_ext_id = cli.car_miposreg_ext_id
        )

After that this: http://pastebin.com/gTFBFurV became this: http://pastebin.com/y13xKcMg

Was it helpful?

Solution

By using left-joins, it uses the index only (provided your table has an index on each respective "ID", "col2" and "othercol" basis. The index is very fast and does not need to go to raw pages to confirm it "exists" or not. The where clause just cares about any of the elements NOT NULL (indicating it DOES exists in the underlying table)

SELECT 
      tbl.* 
   from 
      table as tbl
         LEFT JOIN t1
            ON tbl.id = t1.id
         LEFT JOIN t2
            ON tbl.col2 = t2.col2
         LEFT JOIN t3
            ON tbl.somecol = t3.othercol
   WHERE
         t1.ID is not null
      OR t2.col2 is not null
      OR t3.othercol is not null
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top