Convert Oracle (Cross Join?) to Netezza when using comma separated table list instead of JOIN keywords - oracle

Below is is some Oracle PL/SQL code to join tables without using actual JOIN keywords. This looks like a cross join? How would I convert to Netezza SQL code? That's where I'm stuck.
SELECT COUNT(*)
FROM TABLE_A A, TABLE_A B
WHERE A.X = 'Y' AND A.PATH LIKE '/A/A/A'
AND B.X = 'Z' AND B.PATH LIKE '/B/B/B';
Oracle Cross Join:
http://www.sqlguides.com/sql_cross_join.php
Here's what I tried so far:
SELECT *
from TABLE_A A
cross join (
select * from TABLE_A
) B
WHERE
A.X = 'Y' AND A.PATH LIKE '/A/A/A'
AND B.X = 'Z' AND B.PATH LIKE '/B/B/B';
EDIT:
a_horse_with_no_name:
When I use either syntax in Netezza for the COUNT(*) in the very beginning, it works and returns a count of 60, which matches the first query above when running in Oracle. Without the WHERE clause in Netezza returns 125316 results, which matches the first query above when running in Oracle. When I use either syntax in Netezza for the SELECT * in the very beginning, I get error
ERROR [HY000] ERROR: Record size 70418 exceeds internal limit of 65535 bytes'

Had to use explicit columns in Netezza when doing a CROSS JOIN. Using SELECT * throws the error as indicated in my question EDIT. Also had to escape the '%' character by escaping nothing. Thank you a_horse_with_no_name. Cheers! "Where everybody knows your name." ;-)
select A.CODE, B.CODE, LOWER(A.DIM), LOWER(B.DIM)
FROM TABLE_A A
cross join TABLE_A B
WHERE A.PATH LIKE '\A\A\A%' ESCAPE '' AND A.X = 'Y'
AND B.PATH LIKE '\B\B\B%' ESCAPE '' AND B.X = 'Y'

Related

How can I solve this hive sql problem? (Like join in Hive)

I know Hive only provide equi join. For example, below sql statement.
select *
from A join B
on A.c1 = B.c2
where 1=1;
But I want to execute Like join Query in Hive. For example, below sql statement.
select *
from A join B
on A.c1 like B.c2
where 1=1;
Please let me know if you know the solution in Hive.
How about -
ON A.c1 LIKE concat('%',B.c2,'%')
concat will concatenate % to the c2 data so like operator will work properly.
whole sql will be like -
select * from A join B on A.c1 LIKE concat('%',B.c2,'%') where 1=1;
version - hive 2.1.1

ora 22992 on a LOB field i am not using

I have the following simple oracle query:
select A.field
from table1 A
left join table2#remotedb B on A.id = B.id
Where table B has a BLOB field
It runs fine
If i add a concat to the select:
select A.field||'x'
from table1 A
left join table2#remotedb B on A.id = B.id
I get the following error:
"ora-22992 cannot use lob locators selected from remote tables"
Why adding a concat to a filed which isn't the LOB file is giving me this error?!?
What can i do to avoid it?
check this
with sub1 as
(
select /*+ materialize */ A.field
from table1 A
left join table2#remotedb B on A.id = B.id
)
select field || 'x'
from sub1
I just ran into similar issue. It seems Oracle requires it must be guaranteed any work with clob is avoided at remote side.
Assuming #remotedb is db link to another Oracle db, consider this minimized case:
select dummy from dual; -- works
select to_clob(dummy) from dual; -- works
select dummy from dual#remotedb; -- works
select to_clob(dummy) from dual#remotedb; -- fails - ORA-22992
with m as (select /*+ MATERIALIZE */ dummy from dual#remotedb)
select to_clob(dummy) from m; -- works again, fails without hint
I also tried to find workaround based on forcing computation to local db (select /*+DRIVING_SITE(local)*/ to_clob(r.dummy) from dual local, dual#remotedb r) but with no success.

Invalid Identifier SQL

So i have this:
SELECT p.plantnaam,o.levcode,o.offerteprijs
FROM plant p, offerte o
JOIN (SELECT plantcode , MIN(offerteprijs) AS offprijs
FROM offerte
GROUP BY plantcode) s
ON s.plantcode = p.plantcode
AND s.offprijs = o.offerteprijs
ORDER BY p.plantnaam,l.levcode
Appearently on the 6th row, p.plantcode is suddenly magically an invalid identifier. Why is this? and why are all the others from the exact same table perfectly fine before that point?
The problem is that you are mixing JOINs. You have both implicit and explicit joins. The explicit JOIN syntax with the ON clause has a higher precedence over the implicit join with the commas. As a result the alias for the plant and the offerte tables will not be available in the ON clause. Try using the same JOIN type throughout:
SELECT p.plantnaam, o.levcode, o.offerteprijs
FROM
(
SELECT plantcode , MIN(offerteprijs) AS offprijs
FROM offerte
GROUP BY plantcode
) s
INNER JOIN plant p
ON s.plantcode = p.plantcode
INNER JOIN offerte o
ON s.offprijs = o.offerteprijs
ORDER BY p.plantnaam, l.levcode

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.

Oracle: column ambiguously defined

I know there are lots of questions like these, but my question is not how to get rid of this error but to know how this worked earlier in 9-th version of Oracle.
I've got an old sources written in Ruby and Oracle DB which recently was upgraded to version=11.
I cannot edit data in Oracle DB, only read. so there are two tables lets say: table A(id, name, type, customer) and table B(id,a_id,type,person)
so. there is a query in the source code:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
so in Oracle 9 this worked perfectly but now i've got "column ambiguously defined" error.
What i'd like to know is:
where type = 'A'
is the same as
where a.type = 'A' AND b.type = 'A'
or
where a.type = 'A' OR b.type = 'A'
?
I think this was a bug with the ANSI style join. Use DBMS_XPLAN to find which table was being filtered in the old database.
Or better still, work out from the business logic what they query SHOULD have been.
No, and that's the problem: It could mean
where a.type = 'A'
or it could mean
where b.type = 'A'
with potentially different results; hence the error saying it is ambiguously defined.
I think you should test in Oracle 9 (where you say it works) and compare the output of the ambiguous query:
--- Base
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
with both the non-ambiguous ones:
--- QueryA
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
and:
--- QueryB
select a.id,b.id from a join b on a.id = b.a_id where b.type = 'A'
Something like this would do:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
MINUS
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
(in short):
(Base)
MINUS
(QueryA)
and then:
(QueryA)
MINUS
(Base)
If both of the above MINUS queries return 0 rows, then BASE query is interpreted as QueryA.
Check similarly and compare Base with QueryB.
Another plausible reason for this error is that during (or about the same period with ) the migration, a type column was added in the 2nd table. Do you have old versions of the database tables' definitions to check that?
All - keep in mind there was a major change to the optimization engine for 11g. If you set your query optimizer level to 10.2.x on your 11g instance I bet the query would start working again.
That being said you should provide the alias for it so it's not ambiguous to the database server or the DBA / Developer coming behind you. :)

Resources