最高/最低pl / sql

时间:2015-12-29 22:03:04

标签: sql oracle plsql

我制作了一个程序来显示特定日期特定时间内最高和最低的热门项目。该过程适用于没有错误或异常,并且每个东西都可以运行。如您所见,查询重复两次以显示Items上的第一条记录,但唯一的区别在于Order(ASC和DESC)!有什么办法可以减少代码的数量吗?如何在一个查询中显示最高和最低项目而不是两个?我只想让代码整洁易读。任何帮助将非常感激。

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 个答案:

答案 0 :(得分:1)

使用FIRSTLAST函数在一个查询中获取最大值和最小值:

--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。通常最好将日期保留为日期并避免任何转换功能。