ORA-000932 When joining an xmltype to a varchar field - oracle

a little backstory, i have a comma delimited column in a database, that i have tried to convert into a many to many junction table, so instead of having
ID REPORT
1 5,6,7
i would see
ID REPORT
1 5
1 6
1 7
the query below does just that, and seems to work correctly,
with t as (select id,hqcat from report)
SELECT id, EXTRACT(column_value,'/e/text()') hqcat from t x,
TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE('<ROW><e>'||REPLACE(hqcat,',','</e><e>')||'</e></ROW>'),'//e')))
however when i try to join it to my lookup table by hqcat, i get a ORA-00932 error about inconstant data types, please help me, how do i change my original query to make it work with other tables and joins?
here is the join causing the error:
select *
from BIN03 a11
join ( with t as (select id,hqcat from report)
SELECT id, EXTRACT(column_value,'/e/text()') hqcat from t x,
TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE('<ROW><e>'||REPLACE(hqcat,',','</e><e>')||'</e></ROW>'),'//e')))) a12
on (a11.CODE = a12.HQCAT);
Thank you!
i've also tried to create my new "many to many" view as so:
WITH TAB AS
( (select id ID, hqcat STR from report))
SELECT ID as ID,
REGEXP_SUBSTR (STR, '[^,]+', 1, LEVEL) HQCAT FROM TAB
CONNECT BY LEVEL <= (regexp_count(str,',') + 1);
but this just reduces query speeds by 1000's.....

The (deprecated) extract function returns an XMLType, not a varchar2. You can cast it to the type you want, either in the inline view:
cast(EXTRACT(column_value,'/e/text()') as varchar2(3))
or when comparing the value:
a11.CODE = cast(a12.HQCAT as varchar2(3))
I've guessed the variable size you need, obviously, you might need it to be different. You could also use the XMLType getStringVal() function as shown below.
It seems little odd to mix an old-style cross join with a comma in the inline view's from clause, with ANSI joins in the rest, and you can get odd (or hard to debug, anyway) results doing that. You could also use another CTE for clarity:
with t as (select id, hqcat from report),
a12 as (
select id, extract(column_value,'/e/text()').getstringval() hqcat
from t
cross join table(xmlsequence(extract(xmltype('<ROW><e>'||
replace(hqcat,',','</e><e>')||'</e></ROW>'),'//e')))
)
select *
from a12
join bin03 a11 on a11.code = a12.hqcat;

Related

How to retrieve data from 3 tables using sub query oracle SQL

I want to retrieve users name and there responsibility_key where there end_date is null and i want to convert it to (sysdate+1) using nvl but i am only able to retrieve the responsibility_key not the name please help.
The error in the image says "column ambiguously defined". Take a close look. Your last END_DATE could refer to either the u alias or the table from the subquery. Change it to match the rest of your subquery (FIND_USER_GROUPS_DIRECT.END_DATE)
EDIT
Your query is
select u.USER_NAME, d.responsibility_key from FND_USER u,FND_RESPONSIBILITY_VL d
where responsibility_id in(
select responsibility_id from
FND_USER_RESP_GROUPS_DIRECT WHERE END_USER_RESP_GROUPS_DIRECT.END_DATE=nvl(END_DATE,sysdate+1)) and
u.END_DATE=nvl(END_DATE,SYSDATE + 1)
;
The query isn't formatted, which makes it hard to read.
Not all columns are qualified with table name (or aliases), as mentioned in the comments.
The query currently uses an implicit join.
The query is impossible to understand without seeing the table definitions (desc [table_name]).
For points 1 and 2, a properly formatted query will look something like
select u.user_name, d.responsibility_key
from
fnd_user u,
fnd_responsibility_vl d
where
d.responsibility_id in (
select urgd.responsibility_id
from
fnd_user_resp_groups_direct urgd
where
urgd.end_date = nvl(u.end_date, sysdate+1)
) and
u.end_date = nvl(urgd.end_date, sysdate + 1)
;
This makes it easier to read and in addition to this, you can see that without table definitions I guessed (see point 4) as to which tables the end_date column belongs in your query. If I had to guess, so does Oracle. That means you have an ambiguity problem. To fix it, take a close look at the end_date column as it appears in your original query and where you do not prefix it with anything, you need to prefix it with the appropriate alias (after you have aliased all your tables).
For point 3, you can write your query more clearly with an explicit join and by using aliases for all columns. As for the explicit join I have no idea what your tables look like but one possibility is something like
select u.user_name, d.responsibility_key
from fnd_user u
join fnd_responsibility_vl d
on u.id = d.user_id
where
d.responsibility_id in (
select responsibility_id
from fnd_user_resp_groups_direct urgd
where
urgd.end_date = nvl(u.end_date, sysdate+1)
) and
u.end_date = nvl(urgd.end_date, sysdate+1)
;
If you follow these points you will get to the root of the error.

How to get result from two queries in same output window?

I need output from the below two queries simultaneously in one output window.
QUERY 1
SELECT C.SERVICENAME, C.SERVICEID , B.SOAPIN, B.SOAPOUT, A.TIMESTAMP
FROM Schema1.LG_LOGENTRIES A, Schema1.LG_SOAPREQUESTS B, Schema1.CFG_SOAPSERVICES C
WHERE B.SERVICEID =C.SERVICEID AND
C.SERVICENAME <>'UploadAndPrepareDocumentEx1__sdweb_services_preload' AND
A.ID=B.LOGENTRYID AND B.TIMESTAMP BETWEEN TO_DATE('02/01/2018 11:55:00','dd/mm/yyyy hh24:mi:ss')
AND TO_DATE('02/01/2018 12:03:59','dd/mm/yyyy hh24:mi:ss') AND A.USERID IN (SELECT ID FROM Schema1.CFG_USERS
WHERE NAME=UPPER(TO_CHAR('CGBXGVSG')));
Query 2
SELECT B.JSONIN, B.JSONOUT, A.TIMESTAMP, B.EVENT_MESSAGE, A.PROCESSID, A.status, A.SERVERNAME
FROM Schema1.LG_LOGENTRIES A, Schema1.LG_EVENT B
WHERE B.EVENT_MESSAGE NOT IN ('getFileImage','submitBase64','loadDocumentToSign','getRefData') AND
A.ID=B.LOG_ENTRYID AND B.TIMESTAMP BETWEEN TO_DATE('31/12/2017 13:43:00','dd/mm/yyyy hh24:mi:ss')
AND TO_DATE('31/12/2017 13:53:59','dd/mm/yyyy hh24:mi:ss') AND A.USERID IN (SELECT ID FROM Schema1.CFG_USERS
WHERE NAME=UPPER(TO_CHAR('CTHX8Y2G')));
Run with F5 - you'll get both queries' output in the script panel.
I talk about how this differs here
UNION might be one option, but you'll have to
uniform both column lists (i.e. they have to return the same number of columns which have to be of the same data type), which means that you'd have to add certain NULL columns to both queries
include additional identifier so that you'd know which SELECT returned which values
If you wanted to have them side-by-side, huh, that's not that easy. Thinking loudly: you'd have to have a column that joins those values. Those SELECTs would be inline views. You'd use an aggregate function (such as MAX) along with a DECODE (or CASE) to select values from both queries. Shortly: too much pain.
Now, why do you want to do that? What's wrong with two separate windows, placed side by side?
[EDIT] Showing example of how UNION might look like
select c.servicename, c.serviceid, b.soapin, b.soapout, a.timestamp, to_char(null), to_char(null), to_char(null) , to_number(null), to_char(null), to_char(null)
from ... the rest of your 1st query
union
select null , null , null , null , a.timestamp, b.jsonin , b.jsonout , b.event_message, a.processid , a.status , a.servername
from ... the rest of your 2nd query

can i set up an SSRS report where users input parameters to a table

I have an oracle query that uses a created table as part of the code. Every time I need to run a report I delete current data and import the new data I receive. This is one column of id's. I need to create a report on SSRS in which the user can input this data into said table as a parameter. I have designed a simple report that they can enter some of the id's into a parameter, but there may be times when they need to enter in a few thousand id's, and the report already runs long. Here is what the SSRS code currently says:
select distinct n.id, n.notes
from notes n
join (
select max(seq_num) as seqnum, id from notes group by id) maxresults
on n.id = maxresults.ID
where n.seq_num = maxresults.seqnum
and n.id in (#MyParam)
Is there a way to have MyParam insert data into a table I would join called My_ID, joining as Join My_Id id on n.id = id.id
I do not have permissions to create functions or procedures in the database.
Thank you
You may try the trick with MATERIALIZE hint which normally forces Oracle to create a temporary table :
WITH cte1 AS
( SELECT /*+ MATERIALIZE */ 1 as id FROM DUAL
UNION ALL
SELECT 2 DUAL
)
SELECT a.*
FROM table1 a
INNER JOIN cte1 b ON b.id = a.id

Why is "group by" giving only one column as output?

I have a table something like this:
ID|Value
01|1
02|4
03|12
01|5
02|14
03|22
01|9
02|32
02|62
01|13
03|92
I want to know how much progress have each id made (from initial or minimal value)
so in sybase I can type:
select ID, (value-min(value)) from table group by id;
ID|Value
01|0
01|4
01|8
01|12
02|0
02|10
02|28
02|58
03|0
03|10
03|80
But monetdb does not support this (I am not sure may be cz it uses SQL'99).
Group by only gives one column or may be average of other values but not the desired result.
Are there any alternative to group by in monetdb?
You can achieve this with a self join. The idea is that you build a subselect that gives you the minimum value for each id, and then join that to the original table by id.
SELECT a.id, a.value-b.min_value
FROM "table" a INNER JOIN
(SELECT id, MIN(value) AS min_value FROM "table" GROUP BY id) AS b
ON a.id = b.id;

Rownum in the join condition

Recently I fixed the some bug: there was rownum in the join condition.
Something like this: left join t1 on t1.id=t2.id and rownum<2. So it was supposed to return only one row regardless of the “left join”.
When I looked further into this, I realized that I don’t understand how Oracle evaluates rownum in the "left join" condition.
Let’s create two sampe tables: master and detail.
create table MASTER
(
ID NUMBER not null,
NAME VARCHAR2(100)
)
;
alter table MASTER
add constraint PK_MASTER primary key (ID);
prompt Creating DETAIL...
create table DETAIL
(
ID NUMBER not null,
REF_MASTER_ID NUMBER,
NAME VARCHAR2(100)
)
;
alter table DETAIL
add constraint PK_DETAIL primary key (ID);
alter table DETAIL
add constraint FK_DETAIL_MASTER foreign key (REF_MASTER_ID)
references MASTER (ID);
prompt Disabling foreign key constraints for DETAIL...
alter table DETAIL disable constraint FK_DETAIL_MASTER;
prompt Loading MASTER...
insert into MASTER (ID, NAME)
values (1, 'First');
insert into MASTER (ID, NAME)
values (2, 'Second');
commit;
prompt 2 records loaded
prompt Loading DETAIL...
insert into DETAIL (ID, REF_MASTER_ID, NAME)
values (1, 1, 'REF_FIRST1');
insert into DETAIL (ID, REF_MASTER_ID, NAME)
values (2, 1, 'REF_FIRST2');
insert into DETAIL (ID, REF_MASTER_ID, NAME)
values (3, 1, 'REF_FIRST3');
commit;
prompt 3 records loaded
prompt Enabling foreign key constraints for DETAIL...
alter table DETAIL enable constraint FK_DETAIL_MASTER;
set feedback on
set define on
prompt Done.
Then we have this query :
select * from master t
left join detail d on d.ref_master_id=t.id
The result set is predictable: we have all the rows from the master table and 3 rows from the detail table that matched this condition d.ref_master_id=t.id.
Result Set
Then I added “rownum=1” to the join condition and the result was the same
select * from master t
left join detail d on d.ref_master_id=t.id and rownum=1
The most interesting thing is that I set “rownum<-666” and got the same result again!
select * from master t
left join detail d on d.ref_master_id=t.id and rownum<-666.
Due to the result set we can say that this condition was evaluated as “True” for 3 rows in the detail table. But if I use “inner join” everything goes as supposed to be.
select * from master t
join detail d on d.ref_master_id=t.id and rownum<-666.
This query doesn’t return any row,because I can't imagine rownum to be less then -666 :-)
Moreover, if I use oracle syntax for outer join, using “(+)” everything goes well too.
select * from master m ,detail t
where m.id=t.ref_master_id(+) and rownum<-666.
This query doesn’t return any row too.
Can anyone tell me, what I misunderstand with outer join and rownum?
ROWNUM is a pseudo-attribute of result sets, not of base tables. ROWNUM is defined after rows are selected, but before they're sorted by an ORDER BY clause.
edit: I was mistaken in my previous writeup of ROWNUM, so here's new information:
You can use ROWNUM in a limited way in the WHERE clause, for testing if it's less than a positive integer only. See ROWNUM Pseudocolumn for more details.
SELECT ... WHERE ROWNUM < 10
It's not clear what value ROWNUM has in the context of a JOIN clause, so the results may be undefined. There seems to be some special-case handling of expressions with ROWNUM, for instance WHERE ROWNUM > 10 always returns false. I don't know how ROWNUM<-666 works in your JOIN clause, but it's not meaningful so I would not recommend using it.
In any case, this doesn't help you to fetch the first detail row for each given master row.
To solve this you can use analytic functions and PARTITION, and combine it with Common Table Expressions so you can access the row-number column in a further WHERE condition.
WITH numbered_cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY t.id ORDER BY d.something) AS rn
FROM master t LEFT OUTER JOIN detail d ON d.ref_master_id = t.id
)
SELECT *
FROM numbered_cte
WHERE rn = 1;
if you want to get the first three values from the join condition change the select statement like this.
select *
from (select *
from master t left join detail d on d.ref_master_id=t.id)
where rownum<3;
You will get the required output. Take care on unambigiously defined column names when using *
Let me give an absolute answer which u can run directly with out making any changes to the code.
select *
from (select t.id,t.name,d.id,d.ref_master_id,d.name
from master t left join detail d on d.ref_master_id=t.id)
where rownum<3;
A ROWNUM filter doesn't make any sense in a join, but it isn't being rejected as invalid.
The explain plan will either include the ROWNUM filter or exclude it. If it includes it, it will apply the filter to the detail table after applying the other join condition(s). So if you put in ROWNUM=100 (which will never be satisfied) all the detail rows are excluded and then the outer join kicks in.
If you put in ROWNUM=1 it seems to drop the filter.
And if you query
with
a as (select rownum a_val from dual connect by level < 10),
b as (select rownum*2 b_val from dual connect by level < 10)
select * from a left join b on a_val < b_val and rownum in (1,3);
you get something totally weird.
It probably should be rejected as an error, so expect nonsensical things to happen

Resources