Как узнать минимальное и максимальное значение в разных условиях? - PullRequest
0 голосов
/ 01 июля 2019

Я хочу узнать минимальное и максимальное значение в разных условиях.Я хочу узнать максимальное значение только тогда, когда минимальное значение равно нулю.

Помните, что lc_cont_yymm является переменной, а isMaxRequired, pc_cont_no, ld_Today являются параметрами в функции.Таблица сотрудников - 2125244 строки.основной индекс включен - Cont_no, cont_yymm

SELECT MIN(cont_yymm) INTO lc_cont_yymm
       FROM Employees
       WHERE cont_no = pc_cont_no
       AND   ld_Today BETWEEN eff_date AND term_date;
    IF lc_cont_yymm IS NULL THEN
       IF isMaxRequired THEN
              SELECT MAX(cont_yymm) INTO lc_cont_yymm
                 FROM Employees
                    WHERE cont_no = pc_cont_no
                    AND ld_Today > term_date;
           IF lc_cont_yymm IS NULL THEN
                  RETURN '-2';
           END IF;
       ELSE
              RETURN '-2';
       END IF;
    END IF;
    RETURN lc_cont_yymm;

Этот запрос занимает много времени при многократном вызове для for..loops.Еще больше времени, когда минимальное значение равно нулю и попробуйте найти максимальное значение.Я хочу оптимизировать в лучшую сторону.Пожалуйста, помогите в этом?

1 Ответ

0 голосов
/ 01 июля 2019

Попробуйте объединить два запроса в один как

SELECT CASE WHEN min(cont_yymm) IS NOT NULL 
             AND max(sign(ld_Today - eff_date) * sign(ld_Today - term_date)) < 1 THEN 
                 min(cont_yymm)
       ELSE
         CASE WHEN max(sign(ld_Today - term_date)) THEN
                   max(cont_yymm)
       END 
  INTO lc_cont_yymm
  FROM Employees
 WHERE cont_no = pc_cont_no

Один запрос, один разбор, одна стоимость.

P.S. Чтобы иметь возможность использовать агрегирование для всех терминов, я использовал функцию sign() вместо оператора > или ключевого слова between.

Итак, преобразуйте ваш блок кода в

DECLARE
  isMaxRequired boolean := false; 
  lc_cont_yymm  pls_integer;
--the other variables
BEGIN
  -- some operations
 IF isMaxRequired THEN
  SELECT CASE WHEN min(cont_yymm) IS NOT NULL 
               AND max(sign(ld_Today - eff_date) * sign(ld_Today - term_date)) < 1 THEN 
                   min(cont_yymm)
         ELSE
           CASE WHEN max(sign(ld_Today - term_date)) THEN
                     max(cont_yymm)
         END 
    INTO lc_cont_yymm
    FROM Employees
   WHERE cont_no = pc_cont_no      
 ELSE
        RETURN '-2';
 END IF;
END; 
...