PL SQL 包含多个表的函数

PL SQL function that includes multiple tables

我是 PL SQL 的新手,必须编写一个函数,该函数以 customer_id 作为输入,并且必须为此输出 product_name 的最畅销产品customer_id.

架构如下所示:

我找到了很多包含两个表的简单示例,但我似乎找不到一个必须进行多个连接并使用一个函数,同时只选择最畅销产品的示例。

我可以在这里粘贴很多非常糟糕的代码以及我是如何尝试解决这个问题的,但是对于我目前的知识来说这似乎有点难以理解,因为我一直在学习 PL SQL不到3天就接到了这个任务

使用一些示例数据(最小列集):

SQL> select * from products order by product_id;

PRODUCT_ID PRODUCT_NAME
---------- ----------------
         1 BMW
         2 Audi
SQL> select * From order_items;

PRODUCT_ID CUSTOM   QUANTITY UNIT_PRICE
---------- ------ ---------- ----------
         1 Little        100          1
         1 Little        200          2
         2 Foot          300          3

如果我们检查一些总数:

SQL> select o.product_id,
  2       o.customer_id,
  3       sum(o.quantity * o.unit_price) total
  4     from order_items o
  5     group by o.product_id, o.customer_id;

PRODUCT_ID CUSTOM      TOTAL
---------- ------ ----------
         2 Little        400
         1 Little        100
         2 Foot          900

SQL>

上面写着

  • 对于客户 Little,产品 2 的总销量 = 400 - 这是我们对 Little 的选择
  • 对于客户 Little,产品 1 已售出,总计 = 100
  • 对于客户 Foot,产品 2 的总销量 = 900 - 这是我们对 Foot 的选择

查询可能如下所示:

  • temp CTE 计算每个客户的总数
  • rank_them CTE 对每个客户按降序排列; row_number 这样即使有平局,您也只能得到一种产品
    • 最后,select排名最高的那个

SQL> with
  2  temp as
  3    (select o.product_id,
  4            o.customer_id,
  5            sum(o.quantity * o.unit_price) total
  6     from order_items o
  7     group by o.product_id, o.customer_id
  8    ),
  9  rank_them as
 10    (select t.customer_id,
 11            t.product_id,
 12            row_number() over (partition by t.customer_id order by t.total desc) rn
 13     from temp t
 14    )
 15  select * From rank_them;

CUSTOM PRODUCT_ID         RN
------ ---------- ----------
Foot            2          1  --> for Foot, product 2 ranks as the highest
Little          2          1  --> for Little, product 1 ranks as the highest
Little          1          2

SQL>

移动到函数:

SQL> create or replace function f_product (par_customer_id in order_items.customer_id%type)
  2    return products.product_name%type
  3  is
  4    retval products.product_name%type;
  5  begin
  6    with
  7      temp as
  8        (select o.product_id,
  9                o.customer_id,
 10                sum(o.quantity * o.unit_price) total
 11         from order_items o
 12         group by o.product_id, o.customer_id
 13        ),
 14      rank_them as
 15        (select t.customer_id,
 16                t.product_id,
 17                row_number() over (partition by t.customer_id order by t.total desc) rn
 18         from temp t
 19        )
 20      select p.product_name
 21        into retval
 22      from rank_them r join products p on p.product_id = r.product_id
 23      where r.customer_id = par_customer_id
 24        and r.rn = 1;
 25
 26      return retval;
 27  end;
 28  /

Function created.

SQL>

测试:

SQL> select f_product ('Little') result from dual;

RESULT
--------------------------------------------------------------------------------
Audi

SQL> select f_product ('Foot') result from dual;

RESULT
--------------------------------------------------------------------------------
Audi

SQL>

现在,您可以对其进行改进,以便您关心 未找到数据 问题(当客户没有购买任何东西时),领带(但您随后 return 一个集合或一个 refcursor 而不是一个标量值)等


[编辑] 对不起,ORDERS table 必须包含在临时 CTE 中;您的数据模型是正确的,您无需为此做任何事情 - 我的查询是错误的(小屏幕 + 迟到问题;不是真正的借口,只是说)。

所以:

with 
temp as
  (select i.product_id,
          o.customer_id,
          sum(i.quantity * i.unit_price) total
   from order_items i join orders o on o.order_id = i.order_id
   group by i.product_id, o.customer_id
  ),

我的其余代码 - 否则 - 未修改。