简体   繁体   中英

How can I optimise this sql query?

Here are 4 tables....

  1. tbl_std_working_hour
  2. tbl_attendance
  3. tbl_holiday
  4. tbl_leave

I want to find out the employees absentee reports by this query....but it takes times when I have applied this for many employees...is there any way to simplify this query?

SELECT date
FROM tbl_std_working_hour
WHERE date NOT IN (SELECT date FROM tbl_attendance WHERE emp_id = '$emp_id')
AND date NOT IN (SELECT date FROM tbl_holiday)
AND date NOT IN (SELECT date FROM tbl_leave WHERE emp_id = '$emp_id')
AND total_hour <> '00:00:00'
AND date >= '$start'
AND date <= '$end'
AND emp_id = '$emp_id'

First, I would rewrite using NOT EXISTS :

SELECT wh.date
FROM tbl_std_working_hour wh
WHERE NOT EXISTS (SELECT 1
                  FROM tbl_attendance a
                  WHERE a.date = wh.date AND a.emp_id = wh.emp_id
                 ) AND
      NOT EXISTS (SELECT 1
                  FROM tbl_holiday h
                  WHERE h.date = wh.date
                 ) AND
      NOT EXISTS (SELECT 1
                  FROM tbl_leave l
                  WHERE l.emp_id = wh.emp_id and l.date = wh.date
                 )
WHERE wh.total_hour <> '00:00:00' AND
      wh.date >= '$start' AND
      wh.date <= '$end' AND
      wh.emp_id = '$emp_id';

Then add the following composite (multi-column) indexes:

  • tbl_std_working_hour(emp_id, date, total_hour)
  • tbl_attendance(emp_id, date)
  • tbl_holiday(date) (might already exist if date is the primary key or unique)
  • tbl_leave(emp_id) (might already exist if emp_id is the primary key or unique)

Note that I changed the subqueries to refer to the emp_id in the outer query. This makes it easier to change the emp_id . In addition, your query should be using parameters for the values in the WHERE clause.

This is also a better way that can work better using UNION ALL

SELECT date
FROM tbl_std_working_hour AS tswh
WHERE NOT EXISTS(
    SELECT date FROM tbl_attendance ta WHERE ta.date = tswh.date AND ta.emp_id = tswh.emp_id
    UNION ALL
    SELECT date FROM tbl_holiday th WHERE th.date = tswh.date
    UNION ALL
    SELECT date FROM tbl_leave tl WHERE tl.date = tswh.date AND tl.emp_id = tswh.emp_id)
AND total_hour <> '00:00:00'
AND date >= '$start'
AND date <= '$end'
AND emp_id = '$emp_id'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM