2015-12-29 3 views
3

Я сделал процедуру для отображения наивысших и наименее популярных предметов за определенное время определенной даты. Процедура работает без ошибок или исключений, и каждая вещь функционирует. Как вы можете видеть, запросы повторяются дважды с целью показа первой записи на элементах, но единственные различия заключаются в порядке (ASC и DESC)! Есть ли способ уменьшить количество кода? Как я могу показать наивысшие и самые младшие элементы в одном запросе, а не два? Я хочу только сделать код аккуратным и удобным для чтения. Любая помощь приветствуется.Самый высокий/самый низкий pl/sql

CREATE OR REPLACE PROCEDURE highest_lowest(param IN DATE) 
AS 
    v_pno_low NUMBER(5); 
    v_pno_high NUMBER(5); 
    BEGIN 

    SELECT item_no INTO v_pno_low 
    FROM (
     SELECT 
     items.item_no, 
     sum(items.quantity)     AS total, 
     to_char(prodcution_d, 'dd-mm-yyyy') AS pro_date 
     FROM items 
     JOIN parts ON parts.serial_no = items.serial_no 
     GROUP BY item_no, to_char(prodcution_d, 'dd-mm-yyyy') 
     ORDER BY sum(items.quantity) ASC) 
    WHERE rownum = 1 
      AND pro_date = to_char(param_date, 'mm-yyyy'); 

    dbms_output.put_line('LOWEST ITEM: ' || v_pno_low); 

    SELECT item_no INTO v_pno_low 
    FROM (
     SELECT 
     items.item_no, 
     sum(items.quantity)     AS total, 
     TO_CHAR(prodcution_d, 'dd-mm-yyyy') AS pro_date 
     FROM items 
     JOIN parts ON parts.serial_no = items.serial_no 
     GROUP BY item_no, to_char(prodcution_d, 'dd-mm-yyyy') 
     ORDER BY SUM(items.quantity) DESC) 
    WHERE rownum = 1 
      AND pro_date = to_char(param_date, 'mm-yyyy'); 

    dbms_output.put_line('HIGHEST POPULAR ITEM: ' || v_pno_high); 

    END; 
/
+1

Ваш код хорош и доступен для чтения. Здесь нет необходимости в чрезмерном использовании. – Mxsky

+0

Благодарим вас за ответ. Я думал об уменьшении количества кодирования :) –

+0

Я голосую, чтобы закрыть этот вопрос как не по теме, потому что этот вопрос будет более уместным на http://codereview.stackexchange.com –

ответ

1

Используйте FIRST и LAST функции, чтобы получить как максимум и минимум в одном запросе:

--Step 2: The SERIAL_NO for the smallest and largest quantity per day. 
select 
    min(serial_no) keep (dense_rank first order by quantity_sum) low_serial_no, 
    min(serial_no) keep (dense_rank last order by quantity_sum) high_serial_no 
into v_pno_low, v_pno_high 
from 
(
    --Step 1: Sum of quantity, per day, for the specified month. 
    select 
     items.serial_no, 
     trunc(production_date, 'day') the_date, 
     sum(quantity) quantity_sum 
    from items 
    join parts 
     on items.serial_no = parts.serial_no 
    where trunc(production_date, 'month') = trunc(param_date, 'month') 
    group by items.serial_no, trunc(production_date, 'day') 
); 

Синтаксис KEEP немного запутанным на первом. Внешний запрос получает минимальные значения SERIAL_NO, но только среди строк для первого (самого низкого) QUANTITY_SUM, а затем последнего (самого высокого) QUANTITY_SUM.

В запросе также используется TRUNC вместо TO_CHAR. Обычно лучше указывать даты как даты и избегать любых функций преобразования.

+0

Привет, Джон, и спасибо за ваш комментарий. Ваш ответ действительно полезен, и код работает по мере необходимости. Сказав там, почему я использую TO_CHAR, я хочу показать записи на основе формата «mm-yyyy». Чтобы вызвать процедуру, которую я использовал: exec high_lowest (to_char ('12 -2015 ',' mm-yyyy ')); –

+0

Код работал для меня как SQL, но он говорит ORA-00937: не групповая групповая функция –

+0

Я не уверен, в чем проблема. Возможно, это всего лишь небольшая ошибка синтаксиса, это может помочь отредактировать вопрос и добавить полную новую версию. –