Concatenate Rows

Hi all,

My search can’t find any answer for this in this forum,

I have the block build like,

InvoiceNum Product Salesperson

1000 ABC Mr.X
1000 ABC Mr.Y
2000 XYZ Mr.Z
3000 PQR Mr.A
3000 PQR Mr.B
3000 PQR Mr.C

The client want the block to look like,

InvoiceNum Product Salesperson

1000 ABC Mr.X,Mr.Y
2000 XYZ Mr.Z
3000 PQR Mr.A,Mr.B,Mr.C

Hope i will get a positive answer for this.

Thanks a lot.

Thanks,
Paul


Paulantony (BOB member since 2003-02-14)

Try to “Pivot” the report to display it as “Financial” Data. See if that works out (though it doesn’t have any measures that I’ve seen).

-RM


digpen :us: (BOB member since 2002-08-15)

Hi RM,

Thanks a lot,sorry how to pivot the report to Financial data report?i looked at Format Table—>Pivot can’t see anything as Financial,i do have some measures in the original report.

Thanks,
Paul


Paulantony (BOB member since 2003-02-14)

Paul,

Select the table, then click the button on your toolbar that says “Rotate Table” when you hover over it.


MichaelWelter :vatican_city: (BOB member since 2002-08-08)

Just click on the Pivot-Table icon. It’s just to the left of the Table Information icon. (Or Format > Pivot Table)

-RM


digpen :us: (BOB member since 2002-08-15)

This isn’t a pivot table, it’s a “roll up” of dimensions. Look at the data carefully, and you’ll see what is being requested. The raw data has two rows for 1000 - ABC. The desired output is to concatenate the salesperson values for the combination of other values. BusinessObjects doesn’t provide a feature to do that.

Someone said a while back that some other product (Brio or Cognos, I suspect) had an option to do that at a click of a button. But I’m afraid that what you’re looking for is not available directly. You could try to do some aliases and create some self-joins in designer to do the rolling up at the database level. Or in the past I have written a function to concatenate values and return them as a single string.

But I don’t think you can do what you are asking straight out in the report.

Dave


Dave Rathbun :us: (BOB member since 2002-06-06)

Dave,

That’s true, but you can “emulate” what he wants by using a PIVOT. Turn this into a “PIVOTed” table and then add a sectional break for “Invoice Number”. Remove the Section Object Cell, but leave the Section.

Then set the header as: =Max()
Create a column to the Right as: =Max()

Remove all “Extra” Rows and you should be set. You can move this “table” up higher in the Section to reduce the spacing between rows.

Format the “Sales Person” column so that it no longer has divisor borders.

-RM


digpen :us: (BOB member since 2002-08-15)

Ah, I see where you’re going with this now. I was focusing on the problem and not your solution. :wink:


Dave Rathbun :us: (BOB member since 2002-06-06)

Hi Thanks,

Am i missing something?i can’t see the pivot table option in the Format menu, i am at ver 5.1.3.

Hi Dave can you see tell me more about the function you have written?

Thanks,
Paul


Paulantony (BOB member since 2003-02-14)

Select the table first, then: Format > Rotate Table

You can also just click on the icon, but I believe it’s been available ever since 5.0. You will have to make sure that the Table is selected first.

-RM


digpen :us: (BOB member since 2002-08-15)

It was a sample function, written in Oracle, to concatenate (flatten) an organizational hierarchy. So you would have an object called “reports to” that would build a chain of employees up to the main boss, based on the org chart.

That function was then called in an object in Designer. The net result was that I didn’t need to do what we’ve been talking about in the report. However, it was really just an exercise. If I were going to need that data regularly, I would create a table with the org hierarchy already flattened out.

Dave


Dave Rathbun :us: (BOB member since 2002-06-06)

Hi,

I came across similar question in KX:

[Edit: Removed KX link. You can’t link to internal topics on the KX like you can here, so please don’t post links. Posting instructions like you did below is perfect. – Dave]
(
Go to>: Knowledge Exchange > Reporting and Analysis > Reporting
Search On: Combining results of a column as string, seperated by comma.
)

Crude Solution. Try this:

  1. Make Invoice Number as section header.
  2. Make Product as subsection header
  3. Take off InvoiceNum Product values from detail data. Take off all headers. The report should now look like:

1000
ABC
Mr.X
Mr.Y

2000
XYZ
Mr.Z

3000
PQR
Mr.A
Mr.B
Mr.C

  1. Now Rotate the detail data. Format>Rotate Table. The report will look like:

1000
ABC
Mr.X Mr.Y

2000
XYZ
Mr.Z

3000
PQR
Mr.A Mr.B Mr.C

  1. Now carefully place the cell ‘ABC’ next to 1000. And then carefully place the cell Mr.X next to ‘ABC’. And then Insert>Cell for headers. The report atlast should look what you want.

Hope this helps.

Thanks and Regards,
Srinath M.K


mksrinath (BOB member since 2002-09-19)

Hi all thanks for all your help,

Now i understand what Pivot table is,sorry i am very new to BO and can’t get these buzz words,sorry again my example here shows only three columns,my original report contains 20 columns and when i rotate the table my analyst is not a happy guy,is there any way to do this without rotating the table,thanks a lot for the BO knowledge base info.

Thanks,
Paul


Paulantony (BOB member since 2003-02-14)

I think we need some kind of pre data formatted loading.

We need to write some Pl/SQl scripts to load that kind of data in a table and then create report on it.


man4urheart :india: (BOB member since 2003-02-14)

Paul,

Depending on how your “Analyst” wants to see the data, you have a couple of options. You can create a “single column” table and then pivot it… placing it just underneath a normal table. Then it would appear as a “summary line” under your normal table.

Also note that if you “really” need this option, you can try to pivot it in the database. Are there a “set” number of values for your “Detail” data? If so, then you can use Decodes to generate this.

Otherwise (as Dave has previously stated), you will need to use PL/SQL or some cursors to flatten your data.

-RM


digpen :us: (BOB member since 2002-08-15)

Well, I went back and dug up the function I wrote. Apparently I was feeling particularly ambitious that day, because I not only wrote the function, I documented it. :slight_smile: As far as I remember, this was a “throw-away” example used in a Designer training class when this very issue was brought up. It should serve as an example of how you can dynamically flatten a recursive structure.

This code was written for Oracle 7 but should work for any version of Oracle. This code uses an old version of a BusinessObjects training database which was an HR system. The table structure for the table being processed by this function is shown at the end of this post.

Dave

create or replace function report_to (start_emp char) return varchar2
is begin
declare

-- ************************************************************************* 
-- Function: Report_To
-- Arguements: Report_To (Employee ID)
-- Usage
-- select report_to(employees.employee_id)
--   from employees
--
-- Author Information
-- Dave Rathbun
-- Integra Solutions
-- Dallas, TX  USA
-- ************************************************************************* 
--
-- Description
-- This function is used to construct a list of "report to's" using the
-- company hierarchy. Each employee record has a manager id that references
-- the person that the employee reports to. Using the Oracle "connect by"
-- facility, this function traverses the hierarchy and prints one line of
-- output. For example, if VANGELOS reports to JANES, and JANES reports to
-- BARRY, the output from the function would be:
--  VANGELOS works for JANES works for BARRY
--
-- Special Cases Handled:
-- 1. employee does not report to anyone
--    In this case, the function returns the employee name followed by the
--    phrase ' is the TOP DOG!'
--
-- ************************************************************************* 

  v_emp_id    employees.employee_id%type;   -- obtain data types from table
  v_last_name employees.last_name%type;     -- for maximum code flexibility

  v_once_flag boolean := false;           -- flag for "one time" top boss
  v_report_list varchar2(255);		  -- variable to build list

  -- The cursor below is used to traverse the structure of the company
  -- hierarchy, using the Oracle "connect by prior" facility. The starting
  -- employee id is passed in to the function as a parameter.
  CURSOR bossman IS
  select rtrim(last_name) from employees
  connect by prior manager_id = employee_id
  start with employee_id = v_emp_id;

begin

  v_emp_id := start_emp;			  -- record starting emp id
  v_report_list := null;			  -- set list to null to start

  OPEN bossman;					  -- Open the cursor

  LOOP

    FETCH bossman INTO v_last_name;		  -- fetch a value, and exit if
    EXIT WHEN bossman%NOTFOUND;		 	  -- there is no next value found

    IF v_report_list IS NULL then		  -- if the list is null, then this
       v_report_list := rtrim(v_last_name); -- is the first name found
       v_once_flag := true;			  -- set once flag
    ELSE
       v_once_flag := false;			  -- else, add to list
       v_report_list := v_report_list || ' works for ' ||
                                rtrim(v_last_name);
    END IF;

  end LOOP;

  if v_once_flag then				  -- if only one name processed...
    v_report_list := v_report_list || ' is the TOP DOG!';
  end if;

  return v_report_list;				  -- return name list constructed

end;
end;
/

Table Structure


CREATE TABLE employees (
    employee_id        char(3)   not null,
    last_name          char(20)  not null,
    first_name         char(15)  not null,
    birth_date         date      null,
    address            char(35)  null,
    zip_code           char(5)   null,
    city               char(25)  null,
    telephone          char(12)  null,
    level_id           char(1)   null,
    start_date         date      null,
    position_id        char(2)   null,
    department_id      integer   null,
    manager_id         char(3)   null,
    country_id         integer   null,
    evaluation         char(20)  null,
    PRIMARY KEY (employee_id), 
    FOREIGN KEY (level_id) REFERENCES bolookup.education (level_id),
    FOREIGN KEY (position_id) REFERENCES bolookup.positions (position_id),
    FOREIGN KEY (department_id) REFERENCES bolookup.departments (department_id),
    FOREIGN KEY (manager_id) REFERENCES employees (employee_id),
    FOREIGN KEY (country_id) REFERENCES countries (country_id));

Table Data


/* Add employees */
INSERT INTO employees values (
'T10','BARRY','JOHN','15-NOV-48','416 EAST WASHINGTON','75043','GARLAND',
'214-934-6600','7','13-APR-88','T1', NULL ,NULL, 1, NULL);
commit;
INSERT INTO employees values (
'P73','GETZ','STAN','12-FEB-41','2543 ROCKY POINT DRIVE','75016','IRVING',
'214-978-4245','6','12-JAN-71','L1',4,'T10',1, NULL);
commit;
INSERT INTO employees values (
'K88','NGO','DAVID','10-AUG-49','3219 ESTERS','75013','CARROLTON',
'214-463-8941','5','11-AUG-80','D1',1,'T10',65,'AVERAGE');
commit;
INSERT INTO employees values (
'Z67','IOUNGOS','PEDRO','12-MAR-35','3250 FULLER DRIVE','75044','IRVING',
'214-570-3470','1','16-OCT-63','D1',3,'T10',34,'EXCELLENT');
commit;
INSERT INTO employees values (
'U77','JANES','QUINCY','10-AUG-59','9187 Main','10014','LONG ISLAND',
'607-293-0213','3','04-DEC-87','D1',2,'T10',44,'VERY GOOD');
commit;
INSERT INTO employees values (
'T56','ROSO','LOUIS','12-FEB-69','502 NORTHWEST HIGHWAY','77002','HOUSTON',
'713-617-2242','2','16-MAR-91','L2',4,'P73',1,'AVERAGE');
commit;
INSERT INTO employees values (
'P88','RICHARDS','KEITH','20-FEB-52','101 STOCKTON', '75043','GARLAND',
'214-286-9392','6','16-MAR-83','L1',4,'P73',44,'AVERAGE');
commit;
INSERT INTO employees values (
'B55','OPLIN','JEAN','03-OCT-63','2801 TOWNSGATE ROAD','75012','RICHARDSON',
'214-373-2288','4','01-MAY-87','F1',1,'K88',1,'POOR');
commit;
INSERT INTO employees values (
'X33','WAITS','THOMAS','01-FEB-73','1661 WALDROP','76011','FORT WORTH',
'214-469-7120','1','12-MAR-91','F2',1,'K88',1,'AVERAGE');
commit;
INSERT INTO employees values (
'G56','GILBERTO','EDWARD','01-AUG-64','7240 MOOREFIELD','75065','DALLAS',
'214-765-8941','1','13-MAY-82','F1',1,'K88',39,'ABOVE AVERAGE');
commit;
INSERT INTO employees values (
'U11','TOLEDO','RICHARD','12-JUN-68','2760 CENTRAL','75035','DALLAS',
'214-715-6238','2','27-JUL-89','P1',3,'Z67',34,'VERY GOOD');
commit;
INSERT INTO employees values (
'B52','WILSON','CINDY','13-MAR-44','60 BOSTON STREET','75070','COPPELL',
'214-741-0012','1','13-DEC-78','P1',3,'Z67',1,'AVERAGE');
commit;
INSERT INTO employees values (
'A45','BENJORI','GEORGE','15-DEC-53','1203 STATE STREET','10012','NEW YORK',
'607-726-2442','3','16-MAR-76','M1',2,'U77',39,'AVERAGE');
commit;
INSERT INTO employees values (
'J88','VANGELOS','RENE','12-AUG-65','9400 WEST 7TH','10017','NEW YORK',
'607-257-4559','4','22-MAR-90','M1',2,'U77',33,'EXCELLENT');
commit;
INSERT INTO employees values (
'F55','NYGUYEN','DONALD','01-NOV-70','1020 NORTH PARK','11000','LONG ISLAND',
'607-720-5621','3','16-APR-93','M3',2,'J88',852,'ABOVE AVERAGE');
commit;
INSERT INTO employees values (
'R40','BRUBECK','DAVE','12-APR-68','1935 DAVCOR','11012','RIDGEMAR',
'607-221-9238','2','03-FEB-91','M3',2,'J88',1,'AVERAGE');
commit;
INSERT INTO employees values (
'H11','VAUGHANOFF','SARAH','03-OCT-60','351 PHELPS COURT','11065','NEW YORK',
'607-718-1253','3','06-DEC-87','M2',2,'J88',1,'AVERAGE');
commit;
INSERT INTO employees values (
'U55','ROGERS','TERRY','09-SEP-33','4500 WEST PARKWAY','11022','BROOKLYN',
'607-791-9043','1','04-DEC-56','M2',2,'A45',33,'AVERAGE');
commit;
INSERT INTO employees values (
'P90','DEVISSE','EMILE','10-OCT-50','413 STATTEN','11019','NEW YORK',
'607-341-5160','1','23-DEC-71','M2',2,'A45',33,'POOR');

Dave Rathbun :us: (BOB member since 2002-06-06)

Hi thanks for the valuable function,i have many reports that have the same requirement,anyway for now

I created another table from the same document with just InvoiceNum,Product and salesperson
then set the InvoiceNum and Product as sections,now we have only salesperson in the table,now pivot(rotate) the table it gives the salesperson name as two seperate columns,removed the salesperson name from the original table and then drag the new table to fit in the original table :lol:

Thanks,
Paul


Paulantony (BOB member since 2003-02-14)

Wanted to post another crude way of doing it on Universe side.

Create an object
=+’ ’

Define this object as a measure

Now if this object is used with bunch of dimension it will concatenate the salesperson values for each set of dimensions.

Hope it is useful.

Reema


reemagupta (BOB member since 2002-09-18)

Reema,

That would be a cool trick if it worked, but it’s not working for me. I defined a measure object as follows:

Select: ( EMPLOYEE.EMP_LASTNAME + ‘, ’ + EMPLOYEE.EMP_FIRSTNAME )+’ ’
Project Aggregate: Sum

Then I queried it with a dimension, and the measure column just had a bunch of zeros in it. What am I doing wrong?


MichaelWelter :vatican_city: (BOB member since 2002-08-08)

Michael, try:

Select: EMPLOYEE.EMP_LASTNAME & ', ' 
Project Aggregate: Sum

Double-check that this new measure object is of data type character (and not number). It works for me against the Island Resorts universe.


Andreas :de: (BOB member since 2002-06-20)