procedure P2 is

  v_bundle varchar2(4000)
    /* the composition of a bundle */;
  type bundle_tab_t is table of varchar2(4000)
    index by v_bundle%type;
  v_bundle_tab bundle_tab_t

    /* each element stores the list of bundle_id's
       for a given bundle composition */;

  v_first boolean;
  v_null_element boolean;
  v_last_bundle_id intersections.bundle_id%type := null;

  t varchar2(4000);

  Procedure Record_Bundle_Id (
    p_bundle in v_bundle%type,
    p_bundle_id in intersections.bundle_id%type )is
  begin
    begin

      t := v_bundle_tab(p_bundle);
      v_null_element := false;
    exception when no_data_found
      then v_null_element := true;
    end;

    -- start or add to the comma-separated list of bundle_id's
    if v_null_element

    then
      v_bundle_tab(p_bundle) := To_Char(p_bundle_id);
    else
      v_bundle_tab(p_bundle) := 
        v_bundle_tab(p_bundle) || ', ' || To_Char(p_bundle_id);
    end if;
  end Record_Bundle_Id;

  procedure Initialize_For_Next_Bundle_Id ( p_bundle_id in v_last_bundle_id%type ) is

  begin
    v_last_bundle_id := p_bundle_id;
    v_first := true;
  end Initialize_For_Next_Bundle_Id;
begin
  for j in ( select bundle_id, item_id from intersections
               order by bundle_id, item_id )
  loop
    if v_last_bundle_id is null
    then

      -- Here for the very 1st time only.
      Initialize_For_Next_Bundle_Id ( j.bundle_id );
    elsif j.bundle_id <> v_last_bundle_id
    then
      -- Here each time we finish with a given bundle_id.
      -- Store the bundle_id against the bundle composition key
      Record_Bundle_Id ( v_bundle, v_last_bundle_id );
      Initialize_For_Next_Bundle_Id ( j.bundle_id );
    end if;

    -- Here for 1st or subsequent item_id for given bundle_id.

    -- Start or add to the plus-separated list of item_id's.
    if v_first
    then
      v_bundle := To_Char(j.item_id);
      v_first := false;
    else
      v_bundle:=
        v_bundle || '+' || To_Char(j.item_id);
    end if;
  end loop;
  -- Don't forget the last one!
  Record_Bundle_Id ( v_bundle, v_last_bundle_id );


  -- Report---------------------------------------------------------------------
  Dbms_Output.Put_Line ( Rpad('Bundle composition',20) || Rpad('bundle_id list',20) );
  v_bundle := v_bundle_tab.First;
  while v_bundle is not null
  loop
    if Instr(v_bundle_tab(v_bundle), ',', 1 ) > 0
    then
      Dbms_Output.Put_Line ( Rpad(v_bundle,20) || Rpad(v_bundle_tab(v_bundle),20) );
    end if;
    v_bundle := v_bundle_tab.Next(v_bundle);
  end loop;
end P2;