Sql 遍历循环以查找重复的名称

Sql 遍历循环以查找重复的名称,sql,oracle,plsql,Sql,Oracle,Plsql,我从查询中得到了以下结果,并创建了一个plsql块,在该块中我循环浏览记录并向客户发送电子邮件 匿名块 FOR i IN (SELECT product_no, product_holder,product_catalogue FROM product_master) LOOP mail_send('PRODMASTER',i.product_holder, i.product_no,i.product_catalogue); END LOOP; 我想知道如果产品持有人在查询结果中重复,那么

我从查询中得到了以下结果,并创建了一个plsql块,在该块中我循环浏览记录并向客户发送电子邮件

匿名块

FOR i IN (SELECT product_no, product_holder,product_catalogue FROM
product_master)
LOOP
mail_send('PRODMASTER',i.product_holder, i.product_no,i.product_catalogue);
END LOOP;
我想知道如果
产品持有人
在查询结果中重复,那么最好的方法是什么,而不是发送多封电子邮件,而是发送一封包含相关详细信息的电子邮件。例如,在上述情况下,SMITH重复了两次,因此通过上述方法,SMITH将收到两封电子邮件,而我想用
产品编号和
产品目录向
SMITH
发送一封电子邮件


我怎样才能做到这一点呢?

你可以使用两个循环,为每个产品持有者发送邮件,类似这样

FOR i IN (SELECT distinct product_holder FROM
product_master)
LOOP
 v_products := null;
v_catalogs := null;
for product in (SELECT pm.product_no, pm.product_catalogue FROM
                    product_master pm where pm.product_holder = i.product_holder)
loop
    if v_products is null then
        v_products := product.product_no;
    else
        v_products := v_products ||', ' ||product.product_no;
    end if;
    if v_catalogs is null then
        v_catalogs := product.product_catalogue;
    else
        v_catalogs := v_catalogs ||', ' ||product.product_catalogue;
    end if;
end loop;
mail_send('PRODMASTER',i.product_holder, v_products,v_catalogs);
END LOOP;

您可以使用两个循环,为每个产品持有者发送邮件,类似于这样

FOR i IN (SELECT distinct product_holder FROM
product_master)
LOOP
 v_products := null;
v_catalogs := null;
for product in (SELECT pm.product_no, pm.product_catalogue FROM
                    product_master pm where pm.product_holder = i.product_holder)
loop
    if v_products is null then
        v_products := product.product_no;
    else
        v_products := v_products ||', ' ||product.product_no;
    end if;
    if v_catalogs is null then
        v_catalogs := product.product_catalogue;
    else
        v_catalogs := v_catalogs ||', ' ||product.product_catalogue;
    end if;
end loop;
mail_send('PRODMASTER',i.product_holder, v_products,v_catalogs);
END LOOP;

为此,不要在PL/SQL中的循环中执行循环-使用SQL为您提供可供使用的数据

首先,我们用一些测试数据创建表(我猜是数据类型,您可以用自己的数据类型替换):

对于每个
产品持有者
我们要发送到
邮件发送
程序的是一个集合(数组),其中包含
产品编号
产品目录
。首先是一个包含这两个元素的类型:

create type t_prod_cat_no as object (
   product_no        varchar2(10)
 , product_catalogue varchar2(10)
)
/
然后是该类型的嵌套表类型(集合类型):

create type t_prod_cat_no_table as
   table of t_prod_cat_no
/
然后,程序
mail\u send
应接受
product\u holder
和收集类型:

create or replace procedure mail_send (
   p_parameter        in varchar2
 , p_product_holder   in varchar2
 , p_product_cats_nos in t_prod_cat_no_table
)
is
begin
   dbms_output.put_line('-- BEGIN '||p_parameter||' --');
   dbms_output.put_line('Dear '||p_product_holder);
   dbms_output.put_line('Your products are:');
   for i in 1..p_product_cats_nos.count loop
      dbms_output.put_line(
         'Catalogue: '||p_product_cats_nos(i).product_catalogue||
         ' - No: '||p_product_cats_nos(i).product_no
      );
   end loop;
end mail_send;
/
(我只是使用dbms_输出来模拟构建邮件。)

然后,您可以在SQL中按产品进行分组,并让SQL生成包含以下数据的集合:

begin
   for holder in (
      select pm.product_holder
           , cast(
                collect(
                   t_prod_cat_no(pm.product_no,pm.product_catalogue)
                   order by pm.product_catalogue
                          , pm.product_no
                ) as t_prod_cat_no_table
             ) product_cats_nos 
        from product_master pm
       group by pm.product_holder
       order by pm.product_holder
   ) loop
      mail_send(
         'PRODMASTER'
       , holder.product_holder
       , holder.product_cats_nos
      );
   end loop;
end;
/
上述模块的输出将为:

-- BEGIN PRODMASTER --
Dear HARRY
Your products are:
Catalogue: ARCH - No: 3
-- BEGIN PRODMASTER --
Dear SMITH
Your products are:
Catalogue: TEMP - No: 1
Catalogue: TEMP - No: 2
-- BEGIN PRODMASTER --
Dear TOM
Your products are:
Catalogue: DEPL - No: 4
在SQL中使用
GROUP BY
可以在从PL/SQL到SQL的一次调用中实现所有功能,这比第一次调用获取不同的
产品持有者集
,循环该集合,然后每个
产品持有者
调用一次以获取每个持有者的产品要高效得多

更新:


在上述代码中,向
collect
函数添加了
order by
,表明您可以控制数据在集合中填充的顺序。

为此,不要在PL/SQL中的循环中执行循环-使用SQL为您提供可供使用的数据

首先,我们用一些测试数据创建表(我猜是数据类型,您可以用自己的数据类型替换):

对于每个
产品持有者
我们要发送到
邮件发送
程序的是一个集合(数组),其中包含
产品编号
产品目录
。首先是一个包含这两个元素的类型:

create type t_prod_cat_no as object (
   product_no        varchar2(10)
 , product_catalogue varchar2(10)
)
/
然后是该类型的嵌套表类型(集合类型):

create type t_prod_cat_no_table as
   table of t_prod_cat_no
/
然后,程序
mail\u send
应接受
product\u holder
和收集类型:

create or replace procedure mail_send (
   p_parameter        in varchar2
 , p_product_holder   in varchar2
 , p_product_cats_nos in t_prod_cat_no_table
)
is
begin
   dbms_output.put_line('-- BEGIN '||p_parameter||' --');
   dbms_output.put_line('Dear '||p_product_holder);
   dbms_output.put_line('Your products are:');
   for i in 1..p_product_cats_nos.count loop
      dbms_output.put_line(
         'Catalogue: '||p_product_cats_nos(i).product_catalogue||
         ' - No: '||p_product_cats_nos(i).product_no
      );
   end loop;
end mail_send;
/
(我只是使用dbms_输出来模拟构建邮件。)

然后,您可以在SQL中按产品进行分组,并让SQL生成包含以下数据的集合:

begin
   for holder in (
      select pm.product_holder
           , cast(
                collect(
                   t_prod_cat_no(pm.product_no,pm.product_catalogue)
                   order by pm.product_catalogue
                          , pm.product_no
                ) as t_prod_cat_no_table
             ) product_cats_nos 
        from product_master pm
       group by pm.product_holder
       order by pm.product_holder
   ) loop
      mail_send(
         'PRODMASTER'
       , holder.product_holder
       , holder.product_cats_nos
      );
   end loop;
end;
/
上述模块的输出将为:

-- BEGIN PRODMASTER --
Dear HARRY
Your products are:
Catalogue: ARCH - No: 3
-- BEGIN PRODMASTER --
Dear SMITH
Your products are:
Catalogue: TEMP - No: 1
Catalogue: TEMP - No: 2
-- BEGIN PRODMASTER --
Dear TOM
Your products are:
Catalogue: DEPL - No: 4
在SQL中使用
GROUP BY
可以在从PL/SQL到SQL的一次调用中实现所有功能,这比第一次调用获取不同的
产品持有者集
,循环该集合,然后每个
产品持有者
调用一次以获取每个持有者的产品要高效得多

更新:


在上述代码中,将
order by
添加到
collect
函数中,以显示您可以控制数据在集合中填充的顺序。

PL/SQL Loop-->逐行,也称为Slow by Slow。如果在PL/SQL中也可以这样做的话,千万不要在PL/SQL中这样做。我只是在想,是否有一些列表函数可以在一个组函数中使用,这样你就可以列出每个记录的值,分组在一起?基本上,这就是OP的要求。这样,它就可以在纯SQL中完成。未经测试,这可能只是:PL/SQL循环-->逐行,也就是慢慢来。如果在PL/SQL中也可以这样做的话,千万不要在PL/SQL中这样做。我只是在想,是否有一些列表函数可以在一个组函数中使用,这样你就可以列出每个记录的值,分组在一起?基本上,这就是OP的要求。这样,就可以在纯SQL中完成。未经测试,这可能只是: