是否可以只将部分查询结果存储在存储函数的变量中?

Is it possible to only store a part of my query results in a variable for stored functions?

总的来说,我对 PL/SQL 非常陌生,正在尝试存储函数和过程。

我有以下 select 声明:

SELECT query1.*
  FROM (  SELECT o_custkey, COUNT (o_orderkey) AS ordercount
            FROM orders
        GROUP BY orders.o_custkey) query1,
       (SELECT MAX (query2.ordercount) AS orderhighest
          FROM (  SELECT o_custkey, COUNT (o_orderkey) AS ordercount
                    FROM orders
                GROUP BY orders.o_custkey) query2) query3
 WHERE query1.ordercount = query3.orderhighest;

这条select语句的目标是统计每个客户的订单总数,找出订单最多的客户。查询将 return CustKey & 使用 OrderKey 计算的订单总数。

         O_CUSTKEY ORDERCOUNT
    ---------- ----------
          9787     41

现在我必须找到一种方法来使用结果的 Custkey 部分,将它插入一个变量中,这样我就可以用它来为其余的客户查询另一个 table信息。

但我不太确定如何去做。我听说过使用 SELECT INTO 但我只需要查询结果的 CustKey 部分(即 9787)而不是 OrderCount (41)。

编辑:我尝试根据@Littlefoot 的建议将其更改为存储函数(不带参数),但我不太确定哪里出了问题:

CREATE OR REPLACE FUNCTION CustWithHighestOrder
    RETURN NUMBER
    
IS
    l_custkey  orders.o_custkey%TYPE;
    
BEGIN
   SELECT query1.o_custkey
     INTO l_custkey
     FROM (  SELECT o_custkey, COUNT (o_orderkey) AS ordercount
               FROM orders
           GROUP BY orders.o_custkey) query1,
          (SELECT MAX (query2.ordercount) AS orderhighest
             FROM (  SELECT o_custkey, COUNT (o_orderkey) AS ordercount
                       FROM orders
                   GROUP BY orders.o_custkey) query2) query3
    WHERE query1.ordercount = query3.orderhighest;
    
    
    
END;

我是否应该在结束前做一个 RETURN l_custkey 以便我可以使用变量?

那就不要select *,只需要你需要的。

照原样PL/SQL,声明一个局部变量并select INTO它。

这种方式假定您发布的查询 return 仅一行;否则,它将引发 too_many_rows(因此您必须将其修改为 select 到一个集合中或循环处理数据(这通常是更糟糕的选择))或 no_data_found(你将不得不以某种方式处理)。

DECLARE
   l_custkey  orders.o_custkey%TYPE;
BEGIN
   SELECT query1.o_custkey
     INTO l_custkey
     FROM (  SELECT o_custkey, COUNT (o_orderkey) AS ordercount
               FROM orders
           GROUP BY orders.o_custkey) query1,
          (SELECT MAX (query2.ordercount) AS orderhighest
             FROM (  SELECT o_custkey, COUNT (o_orderkey) AS ordercount
                       FROM orders
                   GROUP BY orders.o_custkey) query2) query3
    WHERE query1.ordercount = query3.orderhighest;
END;

如何将其转换为函数?只需:

CREATE OR REPLACE FUNCTION f_test 
  RETURN orders.o_custkey%TYPE
IS
   l_custkey  orders.o_custkey%TYPE;
BEGIN
   SELECT query1.o_custkey
     INTO l_custkey
     FROM (  SELECT o_custkey, COUNT (o_orderkey) AS ordercount
               FROM orders
           GROUP BY orders.o_custkey) query1,
          (SELECT MAX (query2.ordercount) AS orderhighest
             FROM (  SELECT o_custkey, COUNT (o_orderkey) AS ordercount
                       FROM orders
                   GROUP BY orders.o_custkey) query2) query3
    WHERE query1.ordercount = query3.orderhighest;

  RETURN l_custkey;
END;

所有其他异议仍然有效。此外,我们 通常 将参数传递给函数并在 return 中得到一些东西。虽然,就这样吧。

从 Oracle 12 开始,您可以将查询简化为:

SELECT o_custkey
FROM   orders
GROUP BY o_custkey
ORDER BY COUNT(o_orderkey) DESC
FETCH FIRST ROW WITH TIES;

或者,在 Oracle 12 之前,您可以使用:

SELECT o_custkey
FROM   (
  SELECT o_custkey,
         RANK() OVER (ORDER BY COUNT(o_orderkey) DESC) rnk
  FROM   orders
  GROUP BY o_custkey
)
WHERE  rnk = 1;

Now I have to find a way to use the Custkey part of the result, insert it into a variable so that I'll be able to use it to query another table for the rest of the customer information.

除非该变量将在多个地方用于查询不同的表,否则您最好将第一个查询合并到第二个查询中,在第二个查询中您可以找到额外的客户信息并在单个查询中完成所有操作而不是在 SQL 和 PL/SQL 范围之间重复 context-switches。

如果您随后想在另一个查询中使用它,请使用 JOIN 将其作为 sub-query 包含到该查询中。类似于:

SELECT ot.*
FROM   other_table ot
       INNER JOIN (
         SELECT o_custkey
         FROM   orders
         GROUP BY o_custkey
         ORDER BY COUNT(o_orderkey) DESC
         FETCH FIRST ROW WITH TIES
       ) max_orders
       ON (ot.o_custkey = max_orders.o_custkey)