Informatica Powercenter Add Select LISTAGG query - oracle

I have learning informatica powercenter. I was able to do an INNER JOIN between two VIEWs. I added the INNER JOIN in the User Defined Join but still have to make correct changes in the Sql Query when click on Validate. Do I just need to only add to User Defined Join when I am joining VIEWS?
Here is my problem. I got another VIEWs which is one to many, so this will be my 3rd VIEW to add to the query. I got this running on TOAD. How do I add this to Infromatica? Do I just avoid the Sql Query section and add the entire query into User Defined Query? Do LISTAGG works in Informatica?
If not in the Query for LISTAGG (one-many relationship), is it better or is there a way to do this in the transformation like expression transformation?
Thanks.
This query is a SELECT, LISTAGG, CASE
SELECT PERSON_ID,
FIRST_NAME,
MIDDLE_NAME,
LAST_NAME,
LISTAGG(val,',') WITHIN GROUP (ORDER BY Table2.SKILL_SHORT_DESC )
FROM (SELECT DISTINCT Table1.PERSON_ID,
Table1.FIRST_NAME,
Table1.MIDDLE_NAME,
Table1.LAST_NAME,
(case
when Table2.SKILL_SHORT_DESC = '1' then '1:1'
when Table2.SKILL_SHORT_DESC = '2' then '2:2'
when Table2.SKILL_SHORT_DESC = '3' then '3:3'
when Table2.SKILL_SHORT_DESC = '4' then '4:4'
when Table2.SKILL_SHORT_DESC = '5' then '5:5'
when Table2.SKILL_SHORT_DESC = '6' then '6:6'
when Table2.SKILL_SHORT_DESC = '7' then '7:7'
when Table2.SKILL_SHORT_DESC = '8' then '8:8'
when Table2.SKILL_SHORT_DESC = '9' then '9:9'
else ''
end) as val
FROM Table1
LEFT JOIN Table2
ON Table2.PERSON_ID = Table1.PERSON_ID
)
GROUP BY PERSON_ID,FIRST_NAME,MIDDLE_NAME, LAST_NAME

Yes, LISTAGG should work. Assuming you are using oracle, it should work 10.x and higher version. Frankly, Informatica doesn't care what you write as SQL but its the database where SQL is being issued matters. You can write 'I am batman' and infa will return, 'Invalid syntax'.
Koushik

Please follow below steps,
Get any dummy source from the table
In source qualifier, remove all the ports and create the ports you required
In properties --> Sql query, add the query you have created. No need to provide any user defined joins
Below are the screen shots for better understanding.

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.

cascading Input Control sql query return error: "ORA-01427: single-row subquery returns more than one row"

looking for solution on my sql query error.I'm trying to create second cascading Input Control in JaspersoftServer. The first Input Control works fine, however when I try to create a second cascade IC it returns with the error. I have 3 tables (user, client, user_client), many to many, so 1 linked table (user_client) between them.The 1st Input Control (client) - works well, end user will select the client, the client can have many users, so cascade is the key. Also, as the output, I would like to get not the user_id, but user's firstname and the lastname as one column field. And here is where i'm stuck. I'm pretty sure it is simple syntaxis error, but spent a good couple of hours to figure out what is wrong with it. Is anyone can have a look at it please and indicate where is the problem in my query ?! So far I've done:
select distinct
u.user_id,(
SELECT CONCAT(first_name, surname) AS user_name from tbl_user ),
c.client_id
FROM tbl_user u
left join tbl_user_client uc
on uc.user_id = u.user_id
left join tbl_client c
on c.client_id = uc.client_id
where c.client_id = uc.client_id
order by c.client_id
Thank you in advance.
P.S. JasperServer + Oracle 11g
You're doing an uncorrelated subquery to get the first/last name from the user table. There is no relationship between that subquery:
SELECT CONCAT(first_name, surname) AS user_name from tbl_user
... and the user ID in the main query, so the subquery will attempt to return every first/last name for all users, for every row your joins find.
You don't need to do a subquery at all as you already have the tbl_user information available:
select u.user_id,
CONCAT(u.first_name, u.surname) AS user_name
c.client_id
FROM tbl_user u
left join tbl_user_client uc
on uc.user_id = u.user_id
left join tbl_client c
on c.client_id = uc.client_id
where c.client_id = uc.client_id
order by c.client_id
If you want to put a space between the first and last name you'll either need nested concat() calls, since that function only takes two arguments:
select u.user_id,
CONCAT(u.first_name, CONCAT(' ', u.surname)) AS user_name
...
... or perhaps more readably use the concatenation operator instead:
select u.user_id,
u.first_name ||' '|| u.surname AS user_name
...
If the first control has selected a client and this query is supposed to find the users related to that client, you're joining the tables the wrong way round, aren't you? And you aren't filtering on the selected client - but no idea how that's actually implemented in Jasper. Maybe you do want the entire list and will filter it on the Jasper side.

Oracle Subselect in NVL (Group By required)

I'm facing a problem in Oracle.
I had a SQL where some values were fixed. Now I started replacing them with values from a parameter-table. Some of these fixed values where in a NVL().
Simply said my statement is like this.
SELECT NVL(MAX(t.datefield), to_date('01011900','DDMMYYYY'))
FROM table t;
That works fine.
Now I want to replace the fixed date to a date from my parameter-table with a subselect, which doesn't work at all.
// Works
SELECT NVL(MAX(NULL), 'hello') FROM DUAL;
// Doesn't work
SELECT NVL(MAX(NULL), (SELECT 'hello' FROM DUAL)) FROM DUAL;
The error is:
ORA-00937: .... "not a single-group group function"
I have no idea how to group by a subselect.
Any help is very appreciated! Thanks!
You can't group by a sub-select. However, in order to achieve this your sub-select is only going to be able to return one row. So, change it into a Cartesian join and group by that.
SELECT NVL(MAX(NULL), str)
FROM DUAL
CROSS JOIN ( SELECT 'hello' as str FROM DUAL )
GROUP BY STR
More generally every column that is not included in an aggregate function must be included in the GROUP BY. Plus NVL() is bad; use COALESCE() or CASE instead.

PostgreSQL - migrate a query with 'start with' and 'connect by' in oracle

I have the following query in oracle. I want to convert it to PostgreSQL form. Could someone help me out in this,
SELECT user_id, user_name, reports_to, position
FROM pr_operators
START WITH reports_to = 'dpercival'
CONNECT BY PRIOR user_id = reports_to;
A something like this should work for you (SQL Fiddle):
WITH RECURSIVE q AS (
SELECT po.user_id,po.user_name,po.reports_to,po.position
FROM pr_operators po
WHERE po.reports_to = 'dpercival'
UNION ALL
SELECT po.user_id,po.user_name,po.reports_to,po.position
FROM pr_operators po
JOIN q ON q.user_id=po.reports_to
)
SELECT * FROM q;
You can read more on recursive CTE's in the docs.
Note: your design looks strange -- reports_to contains string literals, yet it is being comapred with user_id which typicaly is of type integer.

Does Oracle implicit conversion depend on joined tables or views

I've faced with a weird problem now. The query itself is huge so I'm not going to post it here (I could post however in case someone needs to see). Now I have a table ,TABLE1, with a CHAR(1) column, COL1. This table column is queried as part of my query. When I filter the recordset for this column I say:
WHERE TAB1.COL1=1
This way the query runs and returns a very big resultset. I've recently updated one of the subqueries to speed up the query. But after this when I write WHERE TAB1.COL1=1 it does not return anything, but if I change it to WHERE TAB1.COL1='1' it gives me the records I need. Notice the WHERE clause with quotes and w/o them. So to make it more clear, before updating one of the sub-queries I did not have to put quotes to check against COL1 value, but after updating I have to. What feature of Oracle is it that I'm not aware of?
EDIT: I'm posting the tw versions of the query in case someone might find it useful
Version 1:
SELECT p.ssn,
pss.pin,
pd.doc_number,
p.surname,
p.name,
p.patronymic,
to_number(p.sex, '9') as sex,
citiz_c.short_name citizenship,
p.birth_place,
p.birth_day as birth_date,
coun_c.short_name as country,
di.name as leg_city,
trim( pa.settlement
|| ' '
|| pa.street) AS leg_street,
pd.issue_date,
pd.issuing_body,
irs.irn,
irs.tpn,
irs.reg_office,
to_number(irs.insurer_type, '9') as insurer_type,
TO_CHAR(sa.REG_CODE)
||CONVERT_INT_TO_DOUBLE_LETTER(TO_NUMBER(SUBSTR(TO_CHAR(sa.DOSSIER_NR, '0999999'), 2, 3)))
||SUBSTR(TO_CHAR(sa.DOSSIER_NR, '0999999'), 5, 4) CONVERTED_SSN_DOSSIER_NR,
fa.snr
FROM
(SELECT pss_t.pin,
pss_t.ssn
FROM EHDIS_INSURANCE.pin_ssn_status pss_t
WHERE pss_t.difference_status < 5
) pss
INNER JOIN SSPF_CENTRE.file_archive fa
ON fa.ssn = pss.ssn
INNER JOIN SSPF_CENTRE.persons p
ON p.ssn = fa.ssn
INNER JOIN
(SELECT pd_2.ssn,
pd_2.type,
pd_2.series,
pd_2.doc_number,
pd_2.issue_date,
pd_2.issuing_body
FROM
--The changed subquery starts here
(SELECT ssn,
MIN(type) AS type
FROM SSPF_CENTRE.person_documents
GROUP BY ssn
) pd_1
INNER JOIN SSPF_CENTRE.person_documents pd_2
ON pd_2.type = pd_1.type
AND pd_2.ssn = pd_1.ssn
) pd
--The changed subquery ends here
ON pd.ssn = p.ssn
INNER JOIN SSPF_CENTRE.ssn_archive sa
ON p.ssn = sa.ssn
INNER JOIN SSPF_CENTRE.person_addresses pa
ON p.ssn = pa.ssn
INNER JOIN
(SELECT i_t.irn,
irs_t.ssn,
i_t.tpn,
i_t.reg_office,
(
CASE i_t.insurer_type
WHEN '4'
THEN '1'
ELSE i_t.insurer_type
END) AS insurer_type
FROM sspf_centre.irn_registered_ssn irs_t
INNER JOIN SSPF_CENTRE.insurers i_t
ON i_t.irn = irs_t.new_irn
OR i_t.old_irn = irs_t.old_irn
WHERE irs_t.is_registration IS NOT NULL
AND i_t.is_real IS NOT NULL
) irs ON irs.ssn = p.ssn
LEFT OUTER JOIN SSPF_CENTRE.districts di
ON di.code = pa.city
LEFT OUTER JOIN SSPF_CENTRE.countries citiz_c
ON p.citizenship = citiz_c.numeric_code
LEFT OUTER JOIN SSPF_CENTRE.countries coun_c
ON pa.country_code = coun_c.numeric_code
WHERE pa.address_flag = '1'--Here's the column value with quotes
AND fa.form_type = 'Q3';
And Version 2:
SELECT p.ssn,
pss.pin,
pd.doc_number,
p.surname,
p.name,
p.patronymic,
to_number(p.sex, '9') as sex,
citiz_c.short_name citizenship,
p.birth_place,
p.birth_day as birth_date,
coun_c.short_name as country,
di.name as leg_city,
trim( pa.settlement
|| ' '
|| pa.street) AS leg_street,
pd.issue_date,
pd.issuing_body,
irs.irn,
irs.tpn,
irs.reg_office,
to_number(irs.insurer_type, '9') as insurer_type,
TO_CHAR(sa.REG_CODE)
||CONVERT_INT_TO_DOUBLE_LETTER(TO_NUMBER(SUBSTR(TO_CHAR(sa.DOSSIER_NR, '0999999'), 2, 3)))
||SUBSTR(TO_CHAR(sa.DOSSIER_NR, '0999999'), 5, 4) CONVERTED_SSN_DOSSIER_NR,
fa.snr
FROM
(SELECT pss_t.pin,
pss_t.ssn
FROM EHDIS_INSURANCE.pin_ssn_status pss_t
WHERE pss_t.difference_status < 5
) pss
INNER JOIN SSPF_CENTRE.file_archive fa
ON fa.ssn = pss.ssn
INNER JOIN SSPF_CENTRE.persons p
ON p.ssn = fa.ssn
INNER JOIN
--The changed subquery starts here
(SELECT ssn,
type,
series,
doc_number,
issue_date,
issuing_body
FROM
(SELECT ssn,
type,
series,
doc_number,
issue_date,
issuing_body,
ROW_NUMBER() OVER (partition BY ssn order by type) rn
FROM SSPF_CENTRE.person_documents
)
WHERE rn = 1
) pd --
--The changed subquery ends here
ON pd.ssn = p.ssn
INNER JOIN SSPF_CENTRE.ssn_archive sa
ON p.ssn = sa.ssn
INNER JOIN SSPF_CENTRE.person_addresses pa
ON p.ssn = pa.ssn
INNER JOIN
(SELECT i_t.irn,
irs_t.ssn,
i_t.tpn,
i_t.reg_office,
(
CASE i_t.insurer_type
WHEN '4'
THEN '1'
ELSE i_t.insurer_type
END) AS insurer_type
FROM sspf_centre.irn_registered_ssn irs_t
INNER JOIN SSPF_CENTRE.insurers i_t
ON i_t.irn = irs_t.new_irn
OR i_t.old_irn = irs_t.old_irn
WHERE irs_t.is_registration IS NOT NULL
AND i_t.is_real IS NOT NULL
) irs ON irs.ssn = p.ssn
LEFT OUTER JOIN SSPF_CENTRE.districts di
ON di.code = pa.city
LEFT OUTER JOIN SSPF_CENTRE.countries citiz_c
ON p.citizenship = citiz_c.numeric_code
LEFT OUTER JOIN SSPF_CENTRE.countries coun_c
ON pa.country_code = coun_c.numeric_code
WHERE pa.address_flag = 1--Here's the column value without quotes
AND fa.form_type = 'Q3';
I've put separating comments for the changed subqueries and the WHERE clause in both queries. Both versions of the subqueries return the same result, one of them is just slower, which is why I decided to update it.
With the most simplistic example I can't reproduce your problem on 11.2.0.3.0 or 11.2.0.1.0.
SQL> create table tmp_test ( a char(1) );
Table created.
SQL> insert into tmp_test values ('1');
1 row created.
SQL> select *
2 from tmp_test
3 where a = 1;
A
-
1
If I then insert a non-numeric value into the table I can confirm Chris' comment "that Oracle will rewrite tab1.col1 = 1 to to_number(tab1.col1) = 1", which implies that you only have numeric characters in the column.
SQL> insert into tmp_test values ('a');
1 row created.
SQL> select *
2 from tmp_test
3 where a = 1;
ERROR:
ORA-01722: invalid number
no rows selected
If you're interested in tracking this down you should gradually reduce the complexity of the query until you have found a minimal, reproducible, example. Oracle can pre-compute a conversion to be used in a JOIN, which as your query is complex seems like a possible explanation of what's happening.
Oracle explicitly recommends against using implicit conversion so it's wiser not to use it at all; as you're finding out. For a start there's no guarantees that your indexes will be used correctly.
Oracle recommends that you specify explicit conversions, rather than rely on implicit or automatic conversions, for these reasons:
SQL statements are easier to understand when you use explicit data type conversion functions.
Implicit data type conversion can have a negative impact on performance, especially if the data type of a column value is converted to that of a constant rather than the other way around.
Implicit conversion depends on the context in which it occurs and may not work the same way in every case. For example, implicit conversion from a datetime value to a VARCHAR2 value may return an unexpected year depending on the value of the NLS_DATE_FORMAT
parameter.
Algorithms for implicit conversion are subject to change across software releases and among Oracle products. Behavior of explicit conversions is more predictable.
If you do only have numeric characters in the column I would highly recommend changing this to a NUMBER(1) column and I would always recommend explicit conversion to avoid a lot of pain in the longer run.
It's hard to tell without the actual query. What I would expect is that TAB1.COL1 is in some way different before and after the refactoring.
Candidates differences are Number vs. CHAR(1) vs. CHAR(x>1) vs VARCHAR2
It is easy to introduce differences like this with subqueries where you join two tables which have different types in the join column and you return different columns in your subquery.
To hunt that issue down you might want to check the exact datatypes of your query. Not sure how to do that right now .. but an idea would be to put it in a view and use sqlplus desc on it.

Resources