繁体   English   中英

将SQL选择查询转换为PL / SQL匿名块(ORACLE)

[英]Converting SQL Select Query to PL/SQL Anonymous Block (ORACLE)

我已经编写了一个标准的SQL Select查询来选择其中销售量最大的邮政编码。 现在,我需要将其转换为匿名PL / SQL块,但是我对PL / SQL仍然很“绿色”,对于如何完成此操作确实没有太多想法。 另外,我需要将LIMIT合并到PL / SQL匿名块中,该块仅在出现领带时显示最低的邮政编码。

这是带有一些数据的表:

CREATE TABLE CUSTOMERS
(customerID     INT     PRIMARY KEY,
customerZip     VARCHAR(15) NOT NULL); 

CREATE TABLE SALES
(saleID         INT     PRIMARY KEY,
customerID      INT,
CONSTRAINT SALES_FK1 FOREIGN KEY (customerID) REFERENCES CUSTOMERS(customerID));

INSERT INTO CUSTOMERS (customerID, customerZIP) VALUES (1, '20636');
INSERT INTO CUSTOMERS (customerID, customerZIP) VALUES (2, '20619');
INSERT INTO CUSTOMERS (customerID, customerZIP) VALUES (3, '20670');
INSERT INTO CUSTOMERS (customerID, customerZIP) VALUES (4, '20670');
INSERT INTO CUSTOMERS (customerID, customerZIP) VALUES (5, '20636');

INSERT INTO SALES (saleID, customerID) VALUES (1, 1);
INSERT INTO SALES (saleID, customerID) VALUES (2, 2);
INSERT INTO SALES (saleID, customerID) VALUES (3, 3);
INSERT INTO SALES (saleID, customerID) VALUES (4, 4);
INSERT INTO SALES (saleID, customerID) VALUES (5, 5);

这是我编写的SQL查询:

SELECT C.customerZip, COUNT (*) AS "MOST_SALES_byZIP"
FROM SALES S
    INNER JOIN CUSTOMERS C
        ON S.customerID = C.customerID
GROUP BY C.customerZip
HAVING COUNT (*) >= ALL
    (SELECT COUNT(*)
        FROM SALES S
            INNER JOIN CUSTOMERS C
                    ON S.customerID = C.customerID
        GROUP BY C.customerZip)
        ORDER BY C.customerZip;

基本上,我首先需要知道如何将其“转换”为PL / SQL匿名块。 然后,我需要知道如何限制结果,以仅在两个或多个之间存在联系时才显示最低的邮政编码。

如果有帮助,我在此处构建了一个SQL提琴模式: http : //sqlfiddle.com/#!4/ca18bf/2

谢谢!

好的PL / SQL编程中有80%是好的SQL编码。

您遇到的问题:首先,在SQL中,要从与大多数销售额相关的数字中选择最低的数字邮政编码,您可以进行联接,然后像以前一样通过邮政编码进行聚合-然后使用聚合LAST函数。 像这样:

select   min(customerzip) keep (dense_rank last order by count(*)) as selected_zip
from     sales inner join customers using (customerid)
group by customerzip
;

SELECTED_ZIP  
---------------
20636   

现在,很容易在匿名块中使用它(如果有必要-无论出于何种原因)。 SET SERVEROUTPUT ON不属于PL / SQL代码; 它是接口程序的命令,用于指示它在屏幕上显示输出缓冲区的内容。

set serveroutput on

declare
  selected_zip integer;
begin
  select   min(customerzip) keep (dense_rank last order by count(*))
    INTO   selected_zip                              -- this is the PL/SQL part!
  from     sales inner join customers using (customerid)
  group by customerzip
  ;
  dbms_output.put_line('Selected zip is: ' || selected_zip);
end;
/

PL/SQL procedure successfully completed.

Selected zip is: 20636

这是一个选择。 创建一个函数,因为匿名块只能打印到STDOUT,它不能将某些内容返回到变量中

Haveing子句被删除,只需按count,zip排序即可,这样就可以按顺序赢取top count,然后再进行top count + top zip的排序。 fetch first 1 rows ONLY添加仅仅获取1行,然后从函数中将其返回。

SQL> CREATE OR REPLACE FUNCTION getlowest RETURN NUMBER AS
        l_ret   NUMBER;
    BEGIN
        FOR r IN (
            SELECT
                c.customerzip,
                COUNT(*) AS "MOST_SALES_byZIP"
            FROM
                sales s
               INNER JOIN customers c ON s.customerid = c.customerid
           GROUP BY
               c.customerzip
           order by
               COUNT(*), c.customerzip
           fetch first 1 rows ONLY
       ) LOOP
           l_ret := r.customerzip;
       END LOOP;

       RETURN l_ret;
   END;
   /
SQL> show errors;
SQL> 
SQL> select getlowest from dual
  2  /
20619
SQL> 

如果目标是返回结果集,那么执行该操作的PL / SQL块将是

-- [Declare the host ref cursor according to the calling tool/language]
-- e.g. in SQL*Plus
var resultset refcursor

begin
    open :resultset for
        select c.customerzip, count(*) as most_sales_byzip
        from   sales s
               join customers c on s.customerid = c.customerid
        group  by c.customerzip
        having count(*) >= all
               ( select count(*) from sales s
                        join customers c on s.customerid = c.customerid
                 group by c.customerzip )
        order by c.customerzip;
end;

从Oracle 12.1开始,您可以使用隐式结果集

declare
    rc sys_refcursor;
begin
    open rc for
        open :resultset for
            select c.customerzip, count(*) as most_sales_byzip
            from   sales s
                   join customers c on s.customerid = c.customerid
            group  by c.customerzip
            having count(*) >= all
                   ( select count(*) from sales s
                            join customers c on s.customerid = c.customerid
                     group by c.customerzip )
            order by c.customerzip;

    dbms_sql.return_result(rc);
end;

但是,我们已经有SQL可以执行此操作,因此似乎没有意义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM