简化NOT IN查询

时间:2014-10-21 03:29:09

标签: mysql

这是电影表: movies table

这是查询的结果表: results table

查询:

SELECT DISTINCT m.movieID, m.title,s.scheduleDateTime, tf.theaterFeatureID, s.scheduleID, m.releasedDate
FROM theater_feature AS tf 
LEFT JOIN schedule AS s ON s.theaterFeatureID = tf.theaterFeatureID 
INNER JOIN movie AS m ON tf.movieID = m.movieID 
WHERE (s.scheduleDateTime > '2014-10-24' OR s.scheduleDateTime IS NULL)
    AND (tf.theaterFeatureID 
        NOT IN ( SELECT s1.theaterFeatureID FROM schedule AS s1 
                WHERE s1.theaterFeatureID = tf.theaterFeatureID 
                AND s1.scheduleDateTime <= '2014-10-24') )
ORDER BY m.releasedDate, s.scheduleDateTime

我在简化此查询时遇到问题,因为它太慢了。 它的作用是:

  • 它会在特定日期显示带有时间表的电影(但不是当前或尚未过去的电影,在此示例中,它是&#39; 2014-10-24&#39;),以及如果电影尚未安排(或为空),则也应包括它。
  • 但是,如果电影通过了第一个资格(电影的日程安排在&#39; 2014-10-24&#39;,或者电影还没有时间表或IS NULL),但是有一个在已经过去的日期安排,该电影不应被包括在内。 简而言之,查询是为了即将推出的电影。

在表格中,电影&#34;地图到星星&#34;和#34; The Maze Runner&#34;因为它们具有已经过去的计划,所以不包括在结果表中。查询已经很好但我想简化它,如果可能的话,替换NOT IN。

我知道这听起来很复杂,但我真的需要弄清楚这一点。如果有人可以帮助我,我真的很感激。

3 个答案:

答案 0 :(得分:0)

查看ID是否存在而不是NOT IN

而不是:

 NOT IN ( SELECT s1.theaterFeatureID FROM schedule AS s1 
                WHERE s1.theaterFeatureID = tf.theaterFeatureID 
                AND s1.scheduleDateTime <= '2014-10-24')

执行:

 NOT EXISTS( SELECT s1.theaterFeatureID FROM schedule AS s1 
                WHERE s1.theaterFeatureID = tf.theaterFeatureID 
                AND s1.scheduleDateTime <= '2014-10-24')

编辑完整查询,为清晰起见

SELECT DISTINCT m.movieID, m.title,s.scheduleDateTime, 
                tf.theaterFeatureID, s.scheduleID, m.releasedDate
FROM theater_feature AS tf 
       LEFT JOIN schedule AS s ON s.theaterFeatureID = tf.theaterFeatureID 
       INNER JOIN movie AS m ON tf.movieID = m.movieID 
    WHERE s.scheduleDateTime > '2014-10-24'
         AND NOT EXISTS ( SELECT s1.theaterFeatureID FROM schedule AS s1 
                WHERE s1.theaterFeatureID = tf.theaterFeatureID 
                AND s1.scheduleDateTime <= '2014-10-24') 
    ORDER BY m.releasedDate, s.scheduleDateTime

在正在查询的列上添加索引也可能会有所帮助。

答案 1 :(得分:0)

SELECT DISTINCT m.movieID, m.title,s.scheduleDateTime, tf.theaterFeatureID, s.scheduleID, m.releasedDate
FROM theater_feature AS tf 
LEFT JOIN schedule AS s ON s.theaterFeatureID = tf.theaterFeatureID 
INNER JOIN movie AS m ON tf.movieID = m.movieID 
WHERE s.scheduleDateTime > '2014-10-24'
ORDER BY m.releasedDate, s.scheduleDateTime

为什么你使用NOT IN条件,它已经使用这个条件获得那些大于日期时间的数据WHERE s.scheduleDateTime > '2014-10-24'

答案 2 :(得分:0)

我建议两件事:

  1. 不要使用DISTINCT;在您的测试数据中,这似乎没有必要
  2. 在schedule.scheduleDateTime

    上添加索引

    CREATE INDEX ix_scheduleDateTime ON schedule(scheduleDateTime)

  3. 然后,以下任何一个都会产生相同的结果(来自sqlfiddle的测试数据):

    SELECT
          m.movieID
        , m.title
        , s.scheduleDateTime
        , tf.theaterFeatureID
        , s.scheduleID
        , m.releasedDate
    FROM theater_feature AS tf
          LEFT JOIN schedule AS s
                      ON s.theaterFeatureID = tf.theaterFeatureID
          INNER JOIN movie m
                      ON tf.movieID = m.movieID
    WHERE (s.scheduleDateTime > '2014-10-24'  OR s.scheduleDateTime IS NULL)
          AND tf.theaterFeatureID
              NOT IN (
                    SELECT
                          s1.theaterFeatureID
                    FROM schedule AS s1
                    WHERE s1.theaterFeatureID = tf.theaterFeatureID
                          AND s1.scheduleDateTime <= '2014-10-24'
              )
    ORDER BY
          m.releasedDate, s.scheduleDateTime
    ;
    

    SELECT
          m.movieID
        , m.title
        , s.scheduleDateTime
        , tf.theaterFeatureID
        , s.scheduleID
        , m.releasedDate
    FROM theater_feature AS tf
          LEFT JOIN schedule AS s
                      ON s.theaterFeatureID = tf.theaterFeatureID
          INNER JOIN movie AS m
                      ON tf.movieID = m.movieID
    WHERE (s.scheduleDateTime > '2014-10-24'  OR s.scheduleDateTime IS NULL)
          AND NOT EXISTS (
                SELECT NULL
                FROM schedule AS s1
                WHERE s1.theaterFeatureID = tf.theaterFeatureID
                      AND s1.scheduleDateTime <= '2014-10-24'
          )
    ORDER BY
          m.releasedDate, s.scheduleDateTime
    ;
    

    在sqlfiddle,执行计划看起来相同