Как улучшить медленный SQL-запрос с агрегатными функциями - PullRequest
0 голосов
/ 02 мая 2019

Я хочу показать десятку клиентов, продажи, маржу, где клиенты зарегистрированы в этом отчетном году.Выполнение запроса занимает около 65 секунд, и оно не принимается :-( Как вы можете видеть, я не очень хорош в SQL и буду очень рад за помощь в улучшении запроса.

SELECT Top 10 
  AcTr.R3, Actor.Nm, 
  SUM(CASE WHEN AcTr.AcNo<='3999' THEN AcAm*-1 ELSE 0 END) AS Sales , 
  SUM(AcAm*-1) AS TB
FROM AcTr, Actor 
WHERE (Actor.CustNo = AcTr.R3) AND
      (Actor.CustNo <> '0') AND
      (Actor.CreDt >= '20180901') AND 
      (Actor.CreDt <= '20190430') AND 
      AcTr.AcYr = '2018' AND
      AcTr.AcPr <= '8' AND
      AcTr.AcNo>='3000' AND
      AcTr.AcNo <= '4999'
GROUP BY AcTr.R3, Actor.Nm 
ORDER BY Sales DESC

1 Ответ

0 голосов
/ 02 мая 2019

Добро пожаловать в сообщество. У вас хорошее начало, но в будущем будет полезно, если вы сможете предоставить (как прокомментировано) объявления таблицы CREATE, чтобы пользователи знали фактические типы данных. Не всегда требуется, но помогает.

Что касается макета вашего запроса, то чаще всего показывается синтаксис JOIN, а не ГДЕ, где отображаются отношения между таблицами, но это происходит во времени и на практике.

Индексы помогают и должны основываться на комбинации критериев WHERE / JOIN И полей группировки. Кроме того, если поля являются числовыми, не ставьте их в кавычки, просто оставляйте их как числа. Например, ваш AcYr, AcPr, AcNo. Я бы подумал, что номер счета действительно будет строковым значением по сравнению с номером для целей бухгалтерского учета.

Я бы предложил следующие индексы для ваших таблиц

Table   Index
Actr    ( AcYr, AcPr, AcNo, R3 )
Actor   ( CustNo, CreDt )

В таблице Actr у меня сначала критерии фильтрации, а в последнем R3, чтобы помочь оптимизировать GROUP BY. Таблица Actor по номеру клиента, затем CreDt (Дата создания ??), и это действительно строка, или это поле даты? Если это так, критерии даты будут выглядеть примерно так: «2018-09-01» и «2019-04-30»

select TOP 10
        Actor.Nm,
        PreSum.Sales,
        PreSm.TB
    from
        ( select
                R3,
                SUM(CASE WHEN AcTr.AcNo <= '3999' 
                    THEN AcAm * -1 ELSE 0 END) AS Sales,
                SUM( AcAm * -1) AS TB
            from
                Actr
            where
                    AcTr.AcYr = 2018
                AND AcTr.AcPr <= 8
                AND AcTr.AcNo >= '3000' 
                AND AcTr.AcNo <= '4999'
            GROUP BY 
                AcTr.R3 ) PreSum
            JOIN Actor
                on PreSum.R3 = Actor.CustNo
                AND Actor.CustNo <> 0
                AND Actor.CreDt >= '20180901'
                AND Actor.CreDt <= '20190430'
    order by
        Sales DESC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...