оптимизация / упрощение курсора sql - PullRequest
1 голос
/ 20 мая 2011

У меня есть приведенный ниже код, и он работает просто отлично, для вычисления ответа требуется всего несколько секунд - мне было интересно, есть ли более быстрый / аккуратный способ написания этого кода - и если да, то что я делаю не так?

спасибо

select case when
    (select LSCCert from matterdatadef where ptmatter=$Matter$) is not null then
    (
        (select case when
            (SELECT top 1 dbo.matterdatadef.ptmatter 
             From dbo.workinprogress, dbo.MatterDataDef 
             where  ptclient=(
                 select top 1 dbo.workinprogress.ptclient 
                 from dbo.workinprogress 
                 where dbo.workinprogress.ptmatter = $matter$)
               and dbo.matterdatadef.LSCCert=(
                 select top 1 dbo.matterdatadef.LSCCert 
                 from dbo.matterdatadef 
                 where dbo.matterdatadef.ptmatter = $matter$)
             )=ptMatter then (
                 SELECT isnull((DateAdd(mm, 6, (
                         select top 1 Date 
                         from OfficeClientLedger 
                         where (pttrans=3) 
                             and ptmatter=$matter$ 
                         order by date desc))), 
                     (DateAdd(mm, 3, (
                         SELECT DateAdd 
                         FROM LAMatter 
                         WHERE  ptMatter = $Matter$)))
             )
        )
        end 
        from lamatter 
        where ptmatter=$matter$)
    )
    end

1 Ответ

1 голос
/ 26 мая 2011

Похоже, что ваш sql был создан из инструмента отчетности. Проблема в том, что вы выполняете запрос SELECT top 1 dbo.matterdatadef.ptmatter... для каждой строки таблицы lamatter. Дальнейшее замедление выполнения, в рамках этого запроса вы пересчитываете значения сравнения для ptclient и LSCCert - значения, которые не будут изменяться во время выполнения.

Лучше использовать правильные объединения и обработать запрос для выполнения каждой части только один раз, избегая коррелированных подзапросов (запросы, которые ссылаются на значения в соединенных таблицах и должны выполняться для каждой строки этой таблицы). Рассчитанные значения в порядке, если они рассчитываются только один раз - то есть из последнего предложения where.

Вот тривиальный пример демонстрации коррелированного подзапроса :

Bad sql:

select a, b from table1 
where a = (select c from table2 where d = b)

Здесь подвыбор выполняется для каждой строки, что будет медленно, особенно без индекса для table2 (d)

Лучше sql:

select a, b from table1, table2
where a = c and d = a

Здесь база данных будет сканировать каждую таблицу не более одного раза, что будет быстро

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