Лучший способ переписать предложение WHERE NOT IN? - PullRequest
3 голосов
/ 05 января 2010

У меня есть запрос, подобный приведенному ниже:

Select ser.key
From dbo.Enrlmt ser     
Where ser.wd >= @FromDate AND ser.wd <= @ThrouDate AND
      ser.EnrlmtStatCode = '4321' AND
      ser.StuExitCatgCode in ('1','2','3','4','5','6','7') AND
      ser.Key not in (select Key 
                           from Enrlmt ser2 
                          where ser2.StartDate <= @AsOfDate 
                            AND ser2.StartDate > ser.wd 
                            AND ser2.EnrlmtStatCode = '4321')

Это очень медленно из-за предложения NOT IN. Я попытался переписать его, используя левое внешнее соединение, чтобы оно выглядело так:

   Select ser.key
     From dbo.Enrlmt ser    
LEFT JOIN dbo.Enrlmt ser2 ON ser.key = ser2.key
                         AND ser2.StartDate <= @AsOfDate 
                         AND ser2.StartDate > ser.wd 
                         AND ser2.EnrlmtStatCode = '4321'
   Where ser2.key is null
     AND ser.wd >= @FromDate 
     AND ser.wd <= @ThrouDate 
     AND ser.EnrlmtStatCode = '4321' 
     AND ser.StuExitCatgCode in ('1','2','3','4','5','6','7')

Что намного быстрее, но результаты не совпадают. Я делаю что-то не так с этим переписать? Есть ли лучший способ сделать это?

Ответы [ 4 ]

2 голосов
/ 05 января 2010

Возможно, это опечатка, но в первом запросе вы сравниваете столбец StuKey , тогда как во втором запросе вы присоединяетесь к Key

По производительности я бы ожидал, что два запроса приведут к очень похожему, если не одинаковому, плану выполнения. Вы должны проверить планы обоих, чтобы увидеть.

Кроме того, убедитесь, что вы очищаете кэш данных между запусками, так как они могут фактически выполнять то же самое, но из-за кэширования данных 2-й кажется более быстрым.

1 голос
/ 05 января 2010

Попробуйте это

  • НЕ СУЩЕСТВУЕТ
  • Возможно, нет необходимости коррелировать ser2.StartDate > ser.wd, потому что ser.wd >= @FromDate?

Также:

  • Если вам нужно использовать ser2.StartDate > ser.wd, это один и тот же тип данных?
  • Все ли типы данных совпадают? например: @FromDate, @ThrouDate, StartDate, wd и т. д.?

следующим образом:

Select
    ser.key
From
    dbo.Enrlmt ser     
Where
    ser.wd >= @FromDate AND ser.wd <= @ThrouDate AND
    ser.EnrlmtStatCode = '4321' AND
    ser.StuExitCatgCode in ('1','2','3','4','5','6','7') AND
    not EXISTS (select *
                           from Enrlmt ser2 
                          where ser2.StartDate <= @AsOfDate 
                            AND ser2.EnrlmtStatCode = '4321'
                            AND ser2.StartDate > @FromDate --ser.wd??
                            AND ser2.Key = ser.Key)
1 голос
/ 05 января 2010

Я думаю, что проблема здесь:

ser.StuKey not in (select StuKey

по сравнению с:

ON ser.key = ser2.key

Таким образом, переписать должно быть:

SELECT      ser.key
FROM        dbo.Enrlmt  ser
LEFT JOIN   Enrlmt      ser2
ON          ser.StuKey         = ser2.Stukey
AND         ser.EnrlmtStatCode = ser2.EnrlmtStatCode
AND         ser2.StartDate     > ser.wd
AND         ser2.StartDate     <= @AsOfDate
WHERE       ser.wd             >= @FromDate 
AND         ser.wd             <= @ThrouDate
AND         ser.EnrlmtStatCode = '4321'
AND         ser.StuExitCatgCode in ('1','2','3','4','5','6','7')
AND         ser2.key IS NULL

(обратите внимание, я также отключил ser2.EnrlmtStatCode = '4321' и переписал его для сравнения столбцов)

0 голосов
/ 05 января 2010

Это будет хороший баланс между эффективностью и ясностью:

    Select ser.key
From
    dbo.Enrlmt ser
    Left Join (select StuKey 
            from Enrlmt 
            where Enrlmt.StartDate <= @AsOfDate AND 
            Enrlmt.EnrlmtStatCode = '4321') As ser2
    ON ser.key = ser2.key And ser2.StartDate > ser.wd
Where
        ser.wd >= @FromDate AND ser.wd <= @ThrouDate AND
        ser.EnrlmtStatCode = '4321' AND
        ser.StuExitCatgCode in ('1','2','3','4','5','6','7') AND
        ser2.key Is Null

Вы можете добиться большей скорости, сделав подзапрос UDF. Для большого количества записей, где подзапрос выполняет большую работу, рассмотрите возможность помещения всего этого в UDF или процедуру и заполнения временной таблицы результатами подзапроса, используя эту таблицу в основном запросе, а затем очистите, удалив временная таблица.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...