barney75
asked on
Displaying data from 3 tables (Oracle)?
Hello,
This is a tricky one... Using only the prod_name hardcoded in the query - I am trying to display...
Prod_id prod_name PROVIDER CUSTOMERS
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- -------
pr001 Sorny Camera co003 Sorny Manufacturer co001 Shop Electronic, co002 Comp World
...Given the 3 tables below:
Products
Prod_id Prod_name client_id
-------------------------- ---------- --------
pr001 Sorny camera co003
Customers
Cust_id Prod_id Company_id
-------------------------- ---------- --
cu001 pr001 co001
cu002 pr001 co002
Companies
Company_id company_name
-------------------------- ------
co001 Shop Electronic
co002 Comp World
co003 Sorny Manufacturer
This is my attempt
SELECT pr.prod_id, prod_name, client_id as PROVIDER, co.company_id || ' ' || co.company_name as CUSTOMERS
FROM Products pr
join customers cu on cu.prod_id=co.prod_id
join companies co on cu.company_id=co.company_i d
WHERE prod_name = 'Sorny Camera'
which displays
Prod_id prod_name PROVIDER CUSTOMERS
-------------------------- ---------- ---------- ---------- ---------- ------
pr001 Sorny Camera co003 co001 Shop Electronic
pr001 Sorny Camera co003 co002 Comp World
Any suggestions?
This is a tricky one... Using only the prod_name hardcoded in the query - I am trying to display...
Prod_id prod_name PROVIDER CUSTOMERS
--------------------------
pr001 Sorny Camera co003 Sorny Manufacturer co001 Shop Electronic, co002 Comp World
...Given the 3 tables below:
Products
Prod_id Prod_name client_id
--------------------------
pr001 Sorny camera co003
Customers
Cust_id Prod_id Company_id
--------------------------
cu001 pr001 co001
cu002 pr001 co002
Companies
Company_id company_name
--------------------------
co001 Shop Electronic
co002 Comp World
co003 Sorny Manufacturer
This is my attempt
SELECT pr.prod_id, prod_name, client_id as PROVIDER, co.company_id || ' ' || co.company_name as CUSTOMERS
FROM Products pr
join customers cu on cu.prod_id=co.prod_id
join companies co on cu.company_id=co.company_i
WHERE prod_name = 'Sorny Camera'
which displays
Prod_id prod_name PROVIDER CUSTOMERS
--------------------------
pr001 Sorny Camera co003 co001 Shop Electronic
pr001 Sorny Camera co003 co002 Comp World
Any suggestions?
note, your concatenated list of customers can't be longer than 4000 characters, otherwise it can't be returned in sql
ASKER
That gives me "ORA-06575 Package or Function STRAGG is in an invalid state".
Would it be easier if i wanted to display this? Or would i still need an aggregate function?
Prod_id prod_name PROVIDER CUSTOMERS
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- -------
pr001 Sorny Camera co003 co001, co002
...From just the two tables below?
Products
Prod_id Prod_name client_id
-------------------------- ---------- --------
pr001 Sorny camera co003
Customers
Cust_id Prod_id Company_id
-------------------------- ---------- --
cu001 pr001 co001
cu002 pr001 co002
Would it be easier if i wanted to display this? Or would i still need an aggregate function?
Prod_id prod_name PROVIDER CUSTOMERS
--------------------------
pr001 Sorny Camera co003 co001, co002
...From just the two tables below?
Products
Prod_id Prod_name client_id
--------------------------
pr001 Sorny camera co003
Customers
Cust_id Prod_id Company_id
--------------------------
cu001 pr001 co001
cu002 pr001 co002
borrowing a function from http://www.orafaq.com/faq/map_rows_to_a_column
SQL> CREATE OR REPLACE FUNCTION rowconcat(q in VARCHAR2) RETURN VARCHAR2 IS
2 ret VARCHAR2(4000);
3 hold VARCHAR2(4000);
4 cur sys_refcursor;
5 BEGIN
6 OPEN cur FOR q;
7 LOOP
8 FETCH cur INTO hold;
9 EXIT WHEN cur%NOTFOUND;
10 IF ret IS NULL THEN
11 ret := hold;
12 ELSE
13 ret := ret || ',' || hold;
14 END IF;
15 END LOOP;
16 RETURN ret;
17 END;
18 /
SELECT pr.prod_id, prod_name, client_id as PROVIDER,
rowconcat (concat(
'select co.company_id || '' '' || co.company_name ',
'from companies co on co.company_id=', cu.company_id
) as CUSTOMER
FROM Products pr
join customers cu on cu.prod_id=co.prod_id
WHERE prod_name = 'Sorny Camera'
ASKER
ORA-00909 Invalid number of arguments for the rowconcat function and
ORA-00712 Invalid number if i add '' to the end of line 23...
ORA-00712 Invalid number if i add '' to the end of line 23...
are there compilation errors in the type or the function? if so, what are they? I use stragg all the time.
Is this a pre-9i db? userdefined aggregates aren't supported until 9
Is this a pre-9i db? userdefined aggregates aren't supported until 9
oops...
SELECT pr.prod_id, prod_name, client_id as PROVIDER,
rowconcat (concat(
'select co.company_id || '' '' || co.company_name ',
'from companies co on co.company_id=', cu.company_id
)) as CUSTOMER
match the brackets.. sorry
SELECT pr.prod_id, prod_name, client_id as PROVIDER,
rowconcat (concat(
'select co.company_id || '' '' || co.company_name ',
'from companies co on co.company_id=', cu.company_id
)) as CUSTOMER
match the brackets.. sorry
ASKER
imitchie, i still get ORA-00712 Invalid number...
the company_id is a NUMBER
the company_name is a VARCHAR2(100 Char)
?
the company_id is a NUMBER
the company_name is a VARCHAR2(100 Char)
?
does it tell you where it fails?
SELECT pr.prod_id, prod_name, client_id as PROVIDER,
rowconcat (concat(
'select co.company_id || '' '' || co.company_name ',
'from companies co on co.company_id=', STR(cu.company_id)
)) as CUSTOMER
SELECT pr.prod_id, prod_name, client_id as PROVIDER,
rowconcat (concat(
'select co.company_id || '' '' || co.company_name ',
'from companies co on co.company_id=', STR(cu.company_id)
)) as CUSTOMER
ASKER
ORA-00909 Invalid number of arguments
Line 2, column 11
Line 2, column 11
oracle only allows 2 strings at a time for concat.. working too much with mysql and sql server
SELECT pr.prod_id, prod_name, client_id as PROVIDER,
rowconcat (
'select co.company_id || '' '' || co.company_name ' ||
'from companies co on co.company_id=' || STR(cu.company_id)
) as CUSTOMER
ASKER
Ok, almost, i'm getting another vague error (makes me appreciate the stack traces in java!)
ORA-00933 SQl command not properly ended
ORA-06512 at 'schema1.ROWCONCAT' line 6
ORA-00933 SQl command not properly ended
ORA-06512 at 'schema1.ROWCONCAT' line 6
barney75, what are the errors in stragg and the underlying type? I definitely don't recommend the rowconcat method. It's going to be a much more expensive operation than using an aggregate. That's why the user-defined aggregates were invented.
If you're on a pre-9i db, then you have to use the rowconcat method but on 9i and up, user-aggregates are the way to go.
Let me know what errors you're getting and I'll try to help you get them compiled.
If you're on a pre-9i db, then you have to use the rowconcat method but on 9i and up, user-aggregates are the way to go.
Let me know what errors you're getting and I'll try to help you get them compiled.
ASKER
sdstuber, the message i am getting is:
ORA-06575 Package or function STRAGG is in an invalid state.
Error at line 1 column 56 (which is the stragg)
and the function itself is marked with a red x (i'm using sql developer)...
ORA-06575 Package or function STRAGG is in an invalid state.
Error at line 1 column 56 (which is the stragg)
and the function itself is marked with a red x (i'm using sql developer)...
what about the type?
stragg uses a type, what's the status of the type?
STRING_AGG_TYPE, any compile errors in it?
stragg uses a type, what's the status of the type?
STRING_AGG_TYPE, any compile errors in it?
ASKER
Doesn't seem to be any errors in the type. Should the contents of the file be showing "create or replace" ?
create or replace FUNCTION stragg(input VARCHAR2)
RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE
USING string_agg_type
create or replace FUNCTION stragg(input VARCHAR2)
RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE
USING string_agg_type
was that error on this query?
SELECT pr.prod_id, prod_name, client_id as PROVIDER,
rowconcat (
'select co.company_id || '' '' || co.company_name ' ||
'from companies co on co.company_id=' || STR(cu.company_id)
) as CUSTOMER
FROM Products pr
join customers cu on cu.prod_id=co.prod_id
WHERE prod_name = 'Sorny Camera'
yes, stragg is created with "create or replace"
CREATE OR REPLACE FUNCTION stragg(input VARCHAR2)
RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE
USING string_agg_type;
/
CREATE OR REPLACE FUNCTION stragg(input VARCHAR2)
RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE
USING string_agg_type;
/
ASKER
Would this happen to have compile errors because it doesn't have the ";" and "/" at the end of the statement?
yes
ASKER
Ok, this could be a stupid question, but how do i create the function so that it has the ";" and the "/" ? If i run the exact script below as it is, it shows without them!
CREATE OR REPLACE FUNCTION stragg(input VARCHAR2)
RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE
USING string_agg_type;
/
CREATE OR REPLACE FUNCTION stragg(input VARCHAR2)
RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE
USING string_agg_type;
/
The ; is end of the create or replace statement
the / is the sqlplus command to run the statement.
It is not part of the function text itself.
are you sure the error is in that function and not in the underlying string_agg_type?
the / is the sqlplus command to run the statement.
It is not part of the function text itself.
are you sure the error is in that function and not in the underlying string_agg_type?
ASKER
ah no - i managed to figure out how to edit the function - added the semicolon and the compile error is gone. However, i can't run the statement now because of "ORA-00937 not a single-group group function" !
what's the statement that gets that error?
ASKER
SELECT pr.prod_id, prod_name, client_id || ', ' || comp.company_name as PROVIDER, co.company_id || ', ' || co.company_name as CUSTOMERS
FROM Products pr, Companies comp
join Customers cu on cu.prod_id=co.prod_id
join Companies co on cu.company_id=co.company_i d
WHERE prod_name = 'Sorny Camera' AND prod_sn='002AB' AND prod_model='DSC'
If i use this group by clause then the SQL will run, but the 'CUSTOMERS' column from the rows whre the prod_id are identical are not concatenated:
group by pr.prod_id, prod_name, client_id, comp.company_name, co.company_id, co.company_name
FROM Products pr, Companies comp
join Customers cu on cu.prod_id=co.prod_id
join Companies co on cu.company_id=co.company_i
WHERE prod_name = 'Sorny Camera' AND prod_sn='002AB' AND prod_model='DSC'
If i use this group by clause then the SQL will run, but the 'CUSTOMERS' column from the rows whre the prod_id are identical are not concatenated:
group by pr.prod_id, prod_name, client_id, comp.company_name, co.company_id, co.company_name
you don't have any aggregates (group functions) in your query.
you're not using stragg so I don't see how it could be the problem.
what's the query with stragg in it that generates the error?
you're not using stragg so I don't see how it could be the problem.
what's the query with stragg in it that generates the error?
ASKER
My mistake...
SELECT pr.prod_id, prod_name, client_id || ', ' || comp.company_name as PROVIDER, stragg(co.company_id || ', ' || co.company_name) as CUSTOMERS
FROM Products pr, Companies comp
join Customers cu on cu.prod_id=co.prod_id
join Companies co on cu.company_id=co.company_i d
WHERE prod_name = 'Sorny Camera' AND prod_sn='002AB' AND prod_model='DSC'
SELECT pr.prod_id, prod_name, client_id || ', ' || comp.company_name as PROVIDER, stragg(co.company_id || ', ' || co.company_name) as CUSTOMERS
FROM Products pr, Companies comp
join Customers cu on cu.prod_id=co.prod_id
join Companies co on cu.company_id=co.company_i
WHERE prod_name = 'Sorny Camera' AND prod_sn='002AB' AND prod_model='DSC'
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks sdstube, working perfect... much appreciated!
CREATE OR REPLACE TYPE "STRING_AGG_TYPE" AS OBJECT(
total VARCHAR2(4000),
STATIC FUNCTION odciaggregateinitialize(sc
RETURN NUMBER,
MEMBER FUNCTION odciaggregateiterate(SELF IN OUT string_agg_type, VALUE IN VARCHAR2)
RETURN NUMBER,
MEMBER FUNCTION odciaggregateterminate(SEL
RETURN NUMBER,
MEMBER FUNCTION odciaggregatemerge(SELF IN OUT string_agg_type, ctx2 IN string_agg_type)
RETURN NUMBER
);
/
CREATE OR REPLACE TYPE BODY string_agg_type
IS
STATIC FUNCTION odciaggregateinitialize(sc
RETURN NUMBER
IS
BEGIN
sctx := string_agg_type(NULL);
RETURN odciconst.success;
END;
MEMBER FUNCTION odciaggregateiterate(SELF IN OUT string_agg_type, VALUE IN VARCHAR2)
RETURN NUMBER
IS
BEGIN
SELF.total := SELF.total || ',' || VALUE;
RETURN odciconst.success;
END;
MEMBER FUNCTION odciaggregateterminate(SEL
RETURN NUMBER
IS
BEGIN
returnvalue := LTRIM(SELF.total, ',');
RETURN odciconst.success;
END;
MEMBER FUNCTION odciaggregatemerge(SELF IN OUT string_agg_type, ctx2 IN string_agg_type)
RETURN NUMBER
IS
BEGIN
SELF.total := SELF.total || ctx2.total;
RETURN odciconst.success;
END;
END;
/
CREATE OR REPLACE FUNCTION stragg(input VARCHAR2)
RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE
USING string_agg_type;
/
SELECT pr.prod_id, prod_name, client_id as PROVIDER, stragg(co.company_id || ' ' || co.company_name) as CUSTOMERS
FROM Products pr
join customers cu on cu.prod_id=co.prod_id
join companies co on cu.company_id=co.company_i
WHERE prod_name = 'Sorny Camera'
group by pr.prod_id,prod_name,clien